@rse/ase 0.9.35 → 0.9.36
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/dst/ase-skills.js +69 -17
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.github/plugin/plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/plugin/skills/ase-arch-discover/SKILL.md +34 -19
- package/plugin/skills/ase-arch-discover/help.md +28 -3
package/dst/ase-skills.js
CHANGED
|
@@ -37,17 +37,19 @@ export class Skills {
|
|
|
37
37
|
const time = pkg.time ?? {};
|
|
38
38
|
const verEntry = version !== "" ? pkg.versions?.[version] : undefined;
|
|
39
39
|
let repository = "";
|
|
40
|
+
let deps = "N.A.";
|
|
40
41
|
if (verEntry !== undefined) {
|
|
41
42
|
const r = verEntry.repository;
|
|
42
43
|
if (typeof r === "string")
|
|
43
44
|
repository = r;
|
|
44
45
|
else if (r !== undefined && typeof r.url === "string")
|
|
45
46
|
repository = r.url;
|
|
47
|
+
deps = Object.keys(verEntry.dependencies ?? {}).length;
|
|
46
48
|
}
|
|
47
|
-
return { version, time, repository };
|
|
49
|
+
return { version, time, repository, deps };
|
|
48
50
|
}
|
|
49
51
|
catch {
|
|
50
|
-
return { version: "", time: {}, repository: "" };
|
|
52
|
+
return { version: "", time: {}, repository: "", deps: "N.A." };
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
/* fetch GitHub stars given a repository URL (or empty string) */
|
|
@@ -83,7 +85,7 @@ export class Skills {
|
|
|
83
85
|
static async fetchMavenInfo(coord) {
|
|
84
86
|
const [groupId, artifactId] = coord.split(":", 2);
|
|
85
87
|
if (groupId === undefined || artifactId === undefined || groupId === "" || artifactId === "")
|
|
86
|
-
return { version: "", created: "", updated: "", repository: "" };
|
|
88
|
+
return { version: "", created: "", updated: "", repository: "", deps: "N.A." };
|
|
87
89
|
try {
|
|
88
90
|
const latest = await Skills.httpLimit(() => ofetch("https://search.maven.org/solrsearch/select" +
|
|
89
91
|
`?q=g:%22${encodeURIComponent(groupId)}%22+AND+a:%22${encodeURIComponent(artifactId)}%22` +
|
|
@@ -113,6 +115,7 @@ export class Skills {
|
|
|
113
115
|
}
|
|
114
116
|
const created = typeof firstTs === "number" ? new Date(firstTs).toISOString() : updated;
|
|
115
117
|
let repository = "";
|
|
118
|
+
let deps = "N.A.";
|
|
116
119
|
if (version !== "") {
|
|
117
120
|
try {
|
|
118
121
|
const pom = await Skills.httpLimit(() => ofetch(`https://repo1.maven.org/maven2/${groupId.replace(/\./g, "/")}` +
|
|
@@ -126,16 +129,31 @@ export class Skills {
|
|
|
126
129
|
if (url !== null)
|
|
127
130
|
repository = url[1];
|
|
128
131
|
}
|
|
132
|
+
/* count the `<dependency>` entries of the direct
|
|
133
|
+
`<dependencies>` block, skipping `test`/`provided`
|
|
134
|
+
scopes; a `<dependencyManagement>` block is ignored
|
|
135
|
+
as it only declares versions, not real dependencies */
|
|
136
|
+
const managed = /<dependencyManagement>[\s\S]*?<\/dependencyManagement>/gi;
|
|
137
|
+
const stripped = pom.replace(managed, "");
|
|
138
|
+
const depRe = /<dependency>([\s\S]*?)<\/dependency>/gi;
|
|
139
|
+
let count = 0;
|
|
140
|
+
let dep;
|
|
141
|
+
while ((dep = depRe.exec(stripped)) !== null) {
|
|
142
|
+
const scope = /<scope>\s*([^<\s]+)\s*<\/scope>/i.exec(dep[1]);
|
|
143
|
+
if (scope === null || (scope[1] !== "test" && scope[1] !== "provided"))
|
|
144
|
+
count++;
|
|
145
|
+
}
|
|
146
|
+
deps = count;
|
|
129
147
|
}
|
|
130
148
|
}
|
|
131
149
|
catch {
|
|
132
150
|
repository = "";
|
|
133
151
|
}
|
|
134
152
|
}
|
|
135
|
-
return { version, created, updated, repository };
|
|
153
|
+
return { version, created, updated, repository, deps };
|
|
136
154
|
}
|
|
137
155
|
catch {
|
|
138
|
-
return { version: "", created: "", updated: "", repository: "" };
|
|
156
|
+
return { version: "", created: "", updated: "", repository: "", deps: "N.A." };
|
|
139
157
|
}
|
|
140
158
|
}
|
|
141
159
|
/* fetch the "Used By" count from `mvnrepository.com` as a downloads proxy
|
|
@@ -180,7 +198,7 @@ export class Skills {
|
|
|
180
198
|
- "JavaScript"/"TypeScript": NPM registry (pacote) + GitHub stars + npm-downloads
|
|
181
199
|
- "Java"/"Kotlin": Maven Central + GitHub stars + mvnrepository.com "Used By"
|
|
182
200
|
- "Unknown": not supported -- return empty result */
|
|
183
|
-
static async info(stack, components) {
|
|
201
|
+
static async info(stack, components, staleMonths = 18, smallScope = false) {
|
|
184
202
|
if (stack === "JavaScript" || stack === "TypeScript") {
|
|
185
203
|
/* per package: kick off packument and downloads in parallel,
|
|
186
204
|
then stars as soon as the packument resolves; across packages
|
|
@@ -194,7 +212,7 @@ export class Skills {
|
|
|
194
212
|
]);
|
|
195
213
|
const created = p.time.created ?? "";
|
|
196
214
|
const updated = p.version !== "" ? (p.time[p.version] ?? "") : "";
|
|
197
|
-
const rank = Skills.computeRank(downloads, stars, created, updated);
|
|
215
|
+
const rank = Skills.computeRank(downloads, stars, created, updated, p.deps, staleMonths, smallScope);
|
|
198
216
|
return {
|
|
199
217
|
name,
|
|
200
218
|
version: p.version,
|
|
@@ -203,6 +221,7 @@ export class Skills {
|
|
|
203
221
|
repository: p.repository,
|
|
204
222
|
stars,
|
|
205
223
|
downloads,
|
|
224
|
+
deps: p.deps,
|
|
206
225
|
rank
|
|
207
226
|
};
|
|
208
227
|
}));
|
|
@@ -222,7 +241,7 @@ export class Skills {
|
|
|
222
241
|
const [i, downloads, stars] = await Promise.all([
|
|
223
242
|
infoPromise, downloadsPromise, starsPromise
|
|
224
243
|
]);
|
|
225
|
-
const rank = Skills.computeRank(downloads, stars, i.created, i.updated);
|
|
244
|
+
const rank = Skills.computeRank(downloads, stars, i.created, i.updated, i.deps, staleMonths, smallScope);
|
|
226
245
|
return {
|
|
227
246
|
name,
|
|
228
247
|
version: i.version,
|
|
@@ -231,6 +250,7 @@ export class Skills {
|
|
|
231
250
|
repository: i.repository,
|
|
232
251
|
stars,
|
|
233
252
|
downloads,
|
|
253
|
+
deps: i.deps,
|
|
234
254
|
rank
|
|
235
255
|
};
|
|
236
256
|
}));
|
|
@@ -253,7 +273,7 @@ export class Skills {
|
|
|
253
273
|
is structurally unavailable, e.g. Maven Central exposes no
|
|
254
274
|
per-artifact download counts) is likewise treated as neutral `1`, so
|
|
255
275
|
such stacks can still be ranked by the remaining metrics. */
|
|
256
|
-
static computeRank(downloads, stars, created, updated) {
|
|
276
|
+
static computeRank(downloads, stars, created, updated, deps, staleMonths, smallScope) {
|
|
257
277
|
const d = typeof downloads === "number" ? downloads + 1 : 1;
|
|
258
278
|
const s = typeof stars === "number" ? stars + 1 : 1;
|
|
259
279
|
const cMs = created !== "" ? Date.parse(created) : NaN;
|
|
@@ -277,7 +297,31 @@ export class Skills {
|
|
|
277
297
|
entry rankable without rewarding the missing date. */
|
|
278
298
|
const lifespan = (!Number.isNaN(cMs) && !Number.isNaN(uMs)) ? Math.max(0, uMs - cMs) : 1;
|
|
279
299
|
const recentness = !Number.isNaN(uMs) ? Math.exp(-Math.max(0, (now - uMs) / msPerDay) / halfLife) : 0.5;
|
|
280
|
-
|
|
300
|
+
let rank = d * s * lifespan * recentness;
|
|
301
|
+
/* hard, caller-tunable staleness penalty on top of the soft
|
|
302
|
+
`recentness` decay: unlike the smooth exp-decay above, this is a
|
|
303
|
+
two-tier *cliff* keyed off the `staleMonths` threshold. Past the
|
|
304
|
+
first tier (`staleMonths`) the rank is cut to `0.3x`, past the
|
|
305
|
+
second tier (`2 x staleMonths`, i.e. long abandoned) to `0.1x`.
|
|
306
|
+
A component below the first tier -- or one whose `updated` date
|
|
307
|
+
is unknown -- is left unpenalized. */
|
|
308
|
+
if (!Number.isNaN(uMs)) {
|
|
309
|
+
const ageMonths = (now - uMs) / msPerDay / 30;
|
|
310
|
+
if (ageMonths > 2 * staleMonths)
|
|
311
|
+
rank *= 0.1;
|
|
312
|
+
else if (ageMonths > staleMonths)
|
|
313
|
+
rank *= 0.3;
|
|
314
|
+
}
|
|
315
|
+
/* small-scope dependency-weight penalty: for a narrow, self-
|
|
316
|
+
contained need, dragging in a heavy dependency tree is usually
|
|
317
|
+
the wrong call, so each real component is demoted in proportion
|
|
318
|
+
to its own number of *direct* dependencies (`1 / (1 + deps)`).
|
|
319
|
+
A zero-dep component is left unpenalized; an unknown `deps` count
|
|
320
|
+
(`"N.A."`) is treated neutrally. This only applies when the
|
|
321
|
+
caller flags the need as small-scope. */
|
|
322
|
+
if (smallScope && typeof deps === "number")
|
|
323
|
+
rank *= 1 / (1 + deps);
|
|
324
|
+
return rank;
|
|
281
325
|
}
|
|
282
326
|
/* compute the per-alternative product-sum (rating) row from a
|
|
283
327
|
weighted decision matrix. Each input row has the shape
|
|
@@ -318,20 +362,28 @@ export class SkillsMCP {
|
|
|
318
362
|
"version + earliest/latest release timestamps from the Maven Central Solr " +
|
|
319
363
|
"search endpoint, the SCM/project URL from the latest POM at `repo1.maven.org`, " +
|
|
320
364
|
"GitHub stars (if applicable), and the \"Used By\" count from `mvnrepository.com` " +
|
|
321
|
-
"as the `downloads` proxy.
|
|
322
|
-
"
|
|
323
|
-
"
|
|
324
|
-
"
|
|
325
|
-
"
|
|
365
|
+
"as the `downloads` proxy. The number of *direct* dependencies is read as `deps` " +
|
|
366
|
+
"(from the packument version entry for NPM, or the latest POM's `<dependencies>` " +
|
|
367
|
+
"block for Maven). Returns a JSON `text` array of " +
|
|
368
|
+
"`{ name, version, created, updated, repository, stars, downloads, deps, rank }` " +
|
|
369
|
+
"objects, sorted in descending order by `rank`. The `rank` applies a two-tier hard " +
|
|
370
|
+
"staleness penalty keyed off `staleMonths` (0.3x past the threshold, 0.1x past twice " +
|
|
371
|
+
"it) and, when `smallScope` is set, a dependency-weight penalty of `1/(1+deps)` so " +
|
|
372
|
+
"dependency-heavy components sink. Failures of individual side calls are isolated " +
|
|
373
|
+
"and reported as `\"N.A.\"` or empty string so every entry has the full shape.",
|
|
326
374
|
inputSchema: {
|
|
327
375
|
stack: z.string()
|
|
328
376
|
.describe("Technology stack: \"JavaScript\", \"TypeScript\", \"Java\", \"Kotlin\", or \"Unknown\""),
|
|
329
377
|
components: z.array(z.string())
|
|
330
|
-
.describe("List of package names (NPM) or Maven coordinates `groupId:artifactId` (Java/Kotlin)")
|
|
378
|
+
.describe("List of package names (NPM) or Maven coordinates `groupId:artifactId` (Java/Kotlin)"),
|
|
379
|
+
staleMonths: z.number().optional()
|
|
380
|
+
.describe("Staleness threshold in months (default 18); a release older than this is rank-penalized"),
|
|
381
|
+
smallScope: z.boolean().optional()
|
|
382
|
+
.describe("If true, penalize each component by its direct-dependency count (small-scope need)")
|
|
331
383
|
}
|
|
332
384
|
}, async (args) => {
|
|
333
385
|
try {
|
|
334
|
-
const result = await Skills.info(args.stack, args.components);
|
|
386
|
+
const result = await Skills.info(args.stack, args.components, args.staleMonths, args.smallScope);
|
|
335
387
|
return {
|
|
336
388
|
content: [{ type: "text", text: JSON.stringify(result) }]
|
|
337
389
|
};
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "http://github.com/rse/ase",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "http://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.36",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
package/plugin/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "http://github.com/rse/ase",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "http://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.36",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ase-arch-discover
|
|
3
|
-
argument-hint: "[--help|-h] [--limit|-l=12] <functionality>"
|
|
3
|
+
argument-hint: "[--help|-h] [--limit|-l=12] [--staleness|-s=18] [--small-scope|-S] <functionality>"
|
|
4
4
|
description: >
|
|
5
5
|
Discover additional, third-party components (libraries/frameworks) for
|
|
6
6
|
the technology stack to provide needed functionality.
|
|
@@ -25,7 +25,7 @@ Discover Components
|
|
|
25
25
|
|
|
26
26
|
<expand name="getopt"
|
|
27
27
|
arg1="ase-arch-discover"
|
|
28
|
-
arg2="--limit|-l=12">
|
|
28
|
+
arg2="--limit|-l=12 --staleness|-s=18 --small-scope|-S">
|
|
29
29
|
$ARGUMENTS
|
|
30
30
|
</expand>
|
|
31
31
|
|
|
@@ -166,18 +166,25 @@ for the technology stack to *provide* the *needed functionality*
|
|
|
166
166
|
entries by Maven coordinate.
|
|
167
167
|
|
|
168
168
|
6. Call the `ase_component_info(stack: "<stack/>", components:
|
|
169
|
-
[ "<package-1/>", ..., "<package-C/>" ]
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
169
|
+
[ "<package-1/>", ..., "<package-C/>" ], staleMonths:
|
|
170
|
+
<getopt-option-staleness/>, smallScope: <getopt-option-small-scope/>)`
|
|
171
|
+
tool of the `ase` MCP server *once* for the entire candidate set of
|
|
172
|
+
discovered packages. When the <getopt-option-small-scope/> option is
|
|
173
|
+
enabled, the ranking treats the <functionality/> as *small-scope*,
|
|
174
|
+
i.e. narrow, self-contained, and low-effort enough that a
|
|
175
|
+
*dependency-free/hand-rolled* implementation is a realistic
|
|
176
|
+
alternative to pulling in a third-party component. The tool
|
|
177
|
+
dispatches internally on <stack/>
|
|
178
|
+
and fetches all metadata in maximum parallel and returns an array
|
|
179
|
+
of objects `{ name, version, created, updated, repository, stars,
|
|
180
|
+
downloads, deps, rank }`. For each component <component-K/>
|
|
181
|
+
(K=1-C) read from its corresponding entry: <version-K/> from
|
|
182
|
+
`version`, <updated-K/> from `updated`, <created-K/> from
|
|
183
|
+
`created`, <repository-K/> from `repository`, <stars-K/> from
|
|
184
|
+
`stars` (numeric or `N.A.`), <downloads-K/> from `downloads`
|
|
185
|
+
(numeric or `N.A.`), <deps-K/> from `deps` (numeric or `N.A.`)
|
|
186
|
+
and <rank-K/> from `rank` (numeric). The returned `rank` already
|
|
187
|
+
reflects the staleness and small-scope dependency penalties.
|
|
181
188
|
|
|
182
189
|
7. Sort, in descending order, the discovered candidate components
|
|
183
190
|
<component-K/> (K=1-C) by their `rank` field and trim the result
|
|
@@ -192,7 +199,15 @@ for the technology stack to *provide* the *needed functionality*
|
|
|
192
199
|
you should not stumble over) is its single most distinguishing
|
|
193
200
|
perspective, and remember this as an <info-K/> (K=1-N) formatted
|
|
194
201
|
like `<type/>: <hint/>` where <type/> is one of `USP`, `Crux`,
|
|
195
|
-
or `Gotcha` and <hint/> is a 1-6 word hint.
|
|
202
|
+
or `Gotcha` and <hint/> is a 1-6 word hint.
|
|
203
|
+
|
|
204
|
+
*Staleness override*: determine the coarse age <age-K/> (like
|
|
205
|
+
`2y`) of the last release from <updated-K/>. If <updated-K/> is
|
|
206
|
+
known and its age exceeds *twice* <getopt-option-staleness/>
|
|
207
|
+
months, *append* to <info-K/> the hint `Gotcha: stale/abandoned
|
|
208
|
+
-- last release <age-K/> ago`; else if its age exceeds
|
|
209
|
+
<getopt-option-staleness/> months, *append* to <info-K/> the
|
|
210
|
+
hint `Gotcha: aging -- last release <age-K/> ago`. Do not output
|
|
196
211
|
anything.
|
|
197
212
|
</step>
|
|
198
213
|
|
|
@@ -217,11 +232,11 @@ for the technology stack to *provide* the *needed functionality*
|
|
|
217
232
|
<template>
|
|
218
233
|
<ase-tpl-bullet-normal/> **COMPONENT RANKING**:
|
|
219
234
|
|
|
220
|
-
| ⚑ *Component* | ▣ *Package* | ❖ *Version* | ↓ *Downloads* | ⎈ *Stars* | ⏲ *Updated* | ☆ *Created* |
|
|
221
|
-
| :------------ | :------------- | -----------: | -----------------: | -------------: | :--------------- | :----------- |
|
|
222
|
-
| **<name-1/>** | `<package-1/>` | <version-1/> | **<downloads-1/>** | **<stars-1/>** | **<updated-1/>** | <created-1/> |
|
|
235
|
+
| ⚑ *Component* | ▣ *Package* | ❖ *Version* | ↓ *Downloads* | ⎈ *Stars* | ⏲ *Updated* | ☆ *Created* | ⚭ *Dep.* |
|
|
236
|
+
| :------------ | :------------- | -----------: | -----------------: | -------------: | :--------------- | :----------- | ---------: |
|
|
237
|
+
| **<name-1/>** | `<package-1/>` | <version-1/> | **<downloads-1/>** | **<stars-1/>** | **<updated-1/>** | <created-1/> | <deps-1/> |
|
|
223
238
|
[...]
|
|
224
|
-
| **<name-N/>** | `<package-N/>` | <version-N/> | **<downloads-N/>** | **<stars-N/>** | **<updated-N/>** | <created-N/> |
|
|
239
|
+
| **<name-N/>** | `<package-N/>` | <version-N/> | **<downloads-N/>** | **<stars-N/>** | **<updated-N/>** | <created-N/> | <deps-N/> |
|
|
225
240
|
</template>
|
|
226
241
|
</step>
|
|
227
242
|
</flow>
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
`ase-arch-discover`
|
|
9
9
|
[`--help`|`-h`]
|
|
10
10
|
[`--limit`|`-l=12`]
|
|
11
|
+
[`--staleness`|`-s=18`]
|
|
12
|
+
[`--small-scope`|`-S`]
|
|
11
13
|
*functionality*
|
|
12
14
|
|
|
13
15
|
## DESCRIPTION
|
|
@@ -20,9 +22,13 @@ The skill determines the project's technology stack (TypeScript,
|
|
|
20
22
|
JavaScript, Kotlin, or Java), derives essential keywords from the
|
|
21
23
|
requested functionality, queries the corresponding package registry
|
|
22
24
|
(NPM or Maven Central), retrieves metadata (version, downloads,
|
|
23
|
-
stars, dates) via the `ase_component_info` MCP tool,
|
|
24
|
-
the top-ranked components as a Markdown table together with
|
|
25
|
-
distinguishing hint (USP, Crux, or Gotcha) per component.
|
|
25
|
+
stars, dates, dependency count) via the `ase_component_info` MCP tool,
|
|
26
|
+
and reports the top-ranked components as a Markdown table together with
|
|
27
|
+
a single distinguishing hint (USP, Crux, or Gotcha) per component.
|
|
28
|
+
|
|
29
|
+
The ranking penalizes *stale* components (last release older than the
|
|
30
|
+
`--staleness` threshold) and, when the `--small-scope` option is given,
|
|
31
|
+
demotes dependency-heavy components.
|
|
26
32
|
|
|
27
33
|
## OPTIONS
|
|
28
34
|
|
|
@@ -31,6 +37,19 @@ distinguishing hint (USP, Crux, or Gotcha) per component.
|
|
|
31
37
|
in the final ranking (default: 12). Raise it for a broader, more
|
|
32
38
|
exhaustive survey, lower it for a quicker, narrower lookup.
|
|
33
39
|
|
|
40
|
+
`--staleness`|`-s=18`:
|
|
41
|
+
The *staleness threshold* in months (default: 18). A component whose
|
|
42
|
+
last release is older than this is rank-penalized and flagged with an
|
|
43
|
+
`aging` gotcha; older than *twice* the threshold, it is penalized
|
|
44
|
+
harder and flagged as `stale/abandoned`.
|
|
45
|
+
|
|
46
|
+
`--small-scope`|`-S`:
|
|
47
|
+
Treat the requested *functionality* as *small-scope* (default: off).
|
|
48
|
+
When enabled, the ranking demotes dependency-heavy components by a
|
|
49
|
+
dependency-weight penalty, since a dependency-free/hand-rolled
|
|
50
|
+
implementation is a realistic alternative for narrow, self-contained
|
|
51
|
+
functionality.
|
|
52
|
+
|
|
34
53
|
## ARGUMENTS
|
|
35
54
|
|
|
36
55
|
*functionality*:
|
|
@@ -57,6 +76,12 @@ Discover a broader set of up to 20 HTTP client components:
|
|
|
57
76
|
❯ /ase-arch-discover --limit 20 HTTP client with retries
|
|
58
77
|
```
|
|
59
78
|
|
|
79
|
+
Discover HTTP clients, flagging any without a release in the last 12 months:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
❯ /ase-arch-discover --staleness 12 HTTP client with retries
|
|
83
|
+
```
|
|
84
|
+
|
|
60
85
|
## SEE ALSO
|
|
61
86
|
|
|
62
87
|
[`ase-arch-analyze`](../ase-arch-analyze/help.md), [`ase-meta-search`](../ase-meta-search/help.md), [`ase-meta-evaluate`](../ase-meta-evaluate/help.md).
|