@mrciphersmith/keryx 0.3.40 → 0.3.41
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 +7 -0
- package/dist/cli.js +174 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,13 @@ keryx auth login <provider> # subscription login (device code / OAuth) or API k
|
|
|
95
95
|
Inside a running session, `/provider` reopens the same add/reconfigure wizard
|
|
96
96
|
and `/connect` switches between providers you already configured.
|
|
97
97
|
|
|
98
|
+
ChatGPT / Codex model discovery reads the current stable Codex version from npm
|
|
99
|
+
metadata and caches it for one day. **Test** in `/connect` (or
|
|
100
|
+
`keryx providers test openai-codex`) always checks for a newer version before
|
|
101
|
+
listing models. This does not install Codex or poll npm in the background.
|
|
102
|
+
If npm is unavailable, a previously discovered version is reused; without a
|
|
103
|
+
cached version, discovery reports the problem instead of guessing a version.
|
|
104
|
+
|
|
98
105
|
Once you have more than one provider connected, `keryx routing` (and, inside a
|
|
99
106
|
session, `/routing`) maps a task category — `review`, `subagents`, and a
|
|
100
107
|
catalogue of others — to a specific model, so reviews and subagent spawns can
|
package/dist/cli.js
CHANGED
|
@@ -14119,7 +14119,7 @@ var package_default;
|
|
|
14119
14119
|
var init_package = __esm(() => {
|
|
14120
14120
|
package_default = {
|
|
14121
14121
|
name: "@mrciphersmith/keryx",
|
|
14122
|
-
version: "0.3.
|
|
14122
|
+
version: "0.3.41",
|
|
14123
14123
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
14124
14124
|
private: false,
|
|
14125
14125
|
publishConfig: {
|
|
@@ -24043,6 +24043,90 @@ var init_openai_subscription = __esm(() => {
|
|
|
24043
24043
|
};
|
|
24044
24044
|
});
|
|
24045
24045
|
|
|
24046
|
+
// src/lib/oauth/codex-catalog-version.ts
|
|
24047
|
+
import { join as join2 } from "path";
|
|
24048
|
+
function validVersion(value) {
|
|
24049
|
+
return typeof value === "string" && value.length <= 64 && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(value);
|
|
24050
|
+
}
|
|
24051
|
+
function loadCache(file, now) {
|
|
24052
|
+
try {
|
|
24053
|
+
const content = readConfigFile(file);
|
|
24054
|
+
if (!content.ok)
|
|
24055
|
+
return;
|
|
24056
|
+
const cache = JSON.parse(content.text);
|
|
24057
|
+
if (typeof cache !== "object" || cache === null)
|
|
24058
|
+
return;
|
|
24059
|
+
const record = cache;
|
|
24060
|
+
if (!validVersion(record.version) || typeof record.fetchedAt !== "number" || !Number.isFinite(record.fetchedAt) || record.fetchedAt < 0 || record.fetchedAt > now)
|
|
24061
|
+
return;
|
|
24062
|
+
return { version: record.version, fetchedAt: record.fetchedAt };
|
|
24063
|
+
} catch {
|
|
24064
|
+
return;
|
|
24065
|
+
}
|
|
24066
|
+
}
|
|
24067
|
+
async function readMetadata(response) {
|
|
24068
|
+
const declared = response.headers.get("content-length");
|
|
24069
|
+
if (declared !== null && Number(declared) > RESPONSE_LIMIT_BYTES)
|
|
24070
|
+
return;
|
|
24071
|
+
if (response.body === null)
|
|
24072
|
+
return;
|
|
24073
|
+
const reader = response.body.getReader();
|
|
24074
|
+
const chunks = [];
|
|
24075
|
+
let size = 0;
|
|
24076
|
+
try {
|
|
24077
|
+
while (true) {
|
|
24078
|
+
const chunk = await reader.read();
|
|
24079
|
+
if (chunk.done)
|
|
24080
|
+
break;
|
|
24081
|
+
size += chunk.value.byteLength;
|
|
24082
|
+
if (size > RESPONSE_LIMIT_BYTES) {
|
|
24083
|
+
await reader.cancel().catch(() => {});
|
|
24084
|
+
return;
|
|
24085
|
+
}
|
|
24086
|
+
chunks.push(chunk.value);
|
|
24087
|
+
}
|
|
24088
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
24089
|
+
} finally {
|
|
24090
|
+
reader.releaseLock();
|
|
24091
|
+
}
|
|
24092
|
+
}
|
|
24093
|
+
async function resolveCodexCatalogVersion(fetchFn, opts = {}) {
|
|
24094
|
+
if (opts.signal?.aborted)
|
|
24095
|
+
return;
|
|
24096
|
+
const now = (opts.now ?? Date.now)();
|
|
24097
|
+
const file = join2(keryxConfigDir(opts.configDir), CACHE_FILE);
|
|
24098
|
+
const cached = loadCache(file, now);
|
|
24099
|
+
if (!opts.forceRefresh && cached !== undefined && now - cached.fetchedAt < CODEX_VERSION_CACHE_TTL_MS)
|
|
24100
|
+
return cached.version;
|
|
24101
|
+
try {
|
|
24102
|
+
const timeout = AbortSignal.timeout(2000);
|
|
24103
|
+
const response = await fetchFn(CODEX_VERSION_REGISTRY_URL, {
|
|
24104
|
+
headers: { Accept: "application/json" },
|
|
24105
|
+
credentials: "omit",
|
|
24106
|
+
redirect: "error",
|
|
24107
|
+
signal: opts.signal === undefined ? timeout : AbortSignal.any([opts.signal, timeout])
|
|
24108
|
+
});
|
|
24109
|
+
if (response.ok) {
|
|
24110
|
+
const body = await readMetadata(response);
|
|
24111
|
+
if (typeof body === "object" && body !== null && "name" in body && body.name === "@openai/codex" && "version" in body && validVersion(body.version) && !opts.signal?.aborted) {
|
|
24112
|
+
const version = body.version;
|
|
24113
|
+
try {
|
|
24114
|
+
ensureKeryxConfigDir(opts.configDir);
|
|
24115
|
+
writeOwnerOnlyFileAtomic(file, JSON.stringify({ version, fetchedAt: now }));
|
|
24116
|
+
} catch {}
|
|
24117
|
+
return version;
|
|
24118
|
+
}
|
|
24119
|
+
}
|
|
24120
|
+
} catch {}
|
|
24121
|
+
return opts.signal?.aborted ? undefined : cached?.version;
|
|
24122
|
+
}
|
|
24123
|
+
var CODEX_VERSION_REGISTRY_URL = "https://registry.npmjs.org/@openai%2Fcodex/latest", CODEX_VERSION_CACHE_TTL_MS, CACHE_FILE = "codex-catalog-version.json", RESPONSE_LIMIT_BYTES;
|
|
24124
|
+
var init_codex_catalog_version = __esm(() => {
|
|
24125
|
+
init_config_dir();
|
|
24126
|
+
CODEX_VERSION_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
24127
|
+
RESPONSE_LIMIT_BYTES = 64 * 1024;
|
|
24128
|
+
});
|
|
24129
|
+
|
|
24046
24130
|
// src/commands/subscription-models.ts
|
|
24047
24131
|
async function fetchOpenAiCodexModels(fetchFn, opts = {}) {
|
|
24048
24132
|
const controller = new AbortController;
|
|
@@ -24051,7 +24135,17 @@ async function fetchOpenAiCodexModels(fetchFn, opts = {}) {
|
|
|
24051
24135
|
try {
|
|
24052
24136
|
const grant = await ensureOpenAiCodexGrant({ fetch: fetchFn, signal: controller.signal, ...opts.configDir !== undefined ? { configDir: opts.configDir } : {} });
|
|
24053
24137
|
authenticated = true;
|
|
24054
|
-
const
|
|
24138
|
+
const clientVersion = await resolveCodexCatalogVersion(fetchFn, {
|
|
24139
|
+
signal: controller.signal,
|
|
24140
|
+
...opts.refreshCatalogVersion !== undefined ? { forceRefresh: opts.refreshCatalogVersion } : {},
|
|
24141
|
+
...opts.configDir !== undefined ? { configDir: opts.configDir } : {}
|
|
24142
|
+
});
|
|
24143
|
+
if (clientVersion === undefined)
|
|
24144
|
+
return { models: [], source: "fallback", failure: {
|
|
24145
|
+
kind: "unreachable",
|
|
24146
|
+
detail: "could not discover the Codex catalog version from npm; no cached version is available"
|
|
24147
|
+
} };
|
|
24148
|
+
const response = await fetchFn(`${OPENAI_CODEX_PICKER.baseUrl}/models?client_version=${clientVersion}`, {
|
|
24055
24149
|
headers: { Authorization: `Bearer ${grant.access}`, "ChatGPT-Account-ID": grant.accountId, originator: "keryx", Accept: "application/json" },
|
|
24056
24150
|
signal: controller.signal,
|
|
24057
24151
|
redirect: "error"
|
|
@@ -24075,9 +24169,10 @@ async function fetchOpenAiCodexModels(fetchFn, opts = {}) {
|
|
|
24075
24169
|
clearTimeout(timer);
|
|
24076
24170
|
}
|
|
24077
24171
|
}
|
|
24078
|
-
var OPENAI_CODEX_PICKER
|
|
24172
|
+
var OPENAI_CODEX_PICKER;
|
|
24079
24173
|
var init_subscription_models = __esm(() => {
|
|
24080
24174
|
init_openai_subscription();
|
|
24175
|
+
init_codex_catalog_version();
|
|
24081
24176
|
OPENAI_CODEX_PICKER = {
|
|
24082
24177
|
name: "openai-codex",
|
|
24083
24178
|
label: "ChatGPT / Codex",
|
|
@@ -26678,7 +26773,10 @@ function providerApiKey(provider, env = process.env) {
|
|
|
26678
26773
|
}
|
|
26679
26774
|
async function testProviderConnection(provider, fetchFn = globalThis.fetch, env = process.env, profiles) {
|
|
26680
26775
|
if (provider.name === "openai-codex")
|
|
26681
|
-
return fetchOpenAiCodexModels(fetchFn, {
|
|
26776
|
+
return fetchOpenAiCodexModels(fetchFn, {
|
|
26777
|
+
refreshCatalogVersion: true,
|
|
26778
|
+
...profiles?.dir !== undefined ? { configDir: profiles.dir } : {}
|
|
26779
|
+
});
|
|
26682
26780
|
const apiKey = providerApiKey(provider, envWithSavedApiKeys(env, profiles?.dir)) ?? provider.apiKey;
|
|
26683
26781
|
return fetchOpenAiCompatModelsDetailed(fetchFn, provider, apiKey, {
|
|
26684
26782
|
timeoutMs: MODELS_FETCH_TIMEOUT_MS,
|
|
@@ -31306,7 +31404,7 @@ var init_wiki_freshness = () => {};
|
|
|
31306
31404
|
|
|
31307
31405
|
// src/harness/tool/builtin/interactive-tools.ts
|
|
31308
31406
|
import { readdir as readdir9 } from "fs/promises";
|
|
31309
|
-
import { basename, dirname, isAbsolute, join as
|
|
31407
|
+
import { basename, dirname, isAbsolute, join as join3, relative, resolve as resolve2, sep } from "path";
|
|
31310
31408
|
import { lstatSync as lstatSync5, realpathSync as realpathSync3 } from "fs";
|
|
31311
31409
|
async function readFromLine(file, startLine, cap) {
|
|
31312
31410
|
const reader = file.stream().getReader();
|
|
@@ -31391,7 +31489,7 @@ function realpathThroughAncestors(absolute) {
|
|
|
31391
31489
|
for (;; ) {
|
|
31392
31490
|
try {
|
|
31393
31491
|
const real = realpathSync3(current);
|
|
31394
|
-
return missing.length === 0 ? real :
|
|
31492
|
+
return missing.length === 0 ? real : join3(real, ...missing.reverse());
|
|
31395
31493
|
} catch {
|
|
31396
31494
|
try {
|
|
31397
31495
|
lstatSync5(current);
|
|
@@ -52592,7 +52690,7 @@ var init_github = __esm(() => {
|
|
|
52592
52690
|
|
|
52593
52691
|
// src/harness/tool/metaproject-adapter.ts
|
|
52594
52692
|
import { lstat as lstat8, readdir as readdir21, readFile as readFile60, realpath as realpath11, stat as stat15 } from "fs/promises";
|
|
52595
|
-
import { isAbsolute as isAbsolute2, join as
|
|
52693
|
+
import { isAbsolute as isAbsolute2, join as join4, relative as relative2, resolve as resolve3 } from "path";
|
|
52596
52694
|
function isMissingExecutable(cause) {
|
|
52597
52695
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
52598
52696
|
return /Executable not found|\bENOENT\b|not found in \$?PATH/i.test(message);
|
|
@@ -52633,7 +52731,7 @@ function portableMemoryPath(candidate) {
|
|
|
52633
52731
|
return !isAbsolute2(normalized) && normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../") ? normalized : null;
|
|
52634
52732
|
}
|
|
52635
52733
|
function confineToWiki(cwd, candidate) {
|
|
52636
|
-
const wikiRoot =
|
|
52734
|
+
const wikiRoot = join4(cwd, ".metaproject", "wiki");
|
|
52637
52735
|
const target = resolve3(wikiRoot, candidate);
|
|
52638
52736
|
const rel = relative2(wikiRoot, target);
|
|
52639
52737
|
if (rel === "") {
|
|
@@ -52676,7 +52774,7 @@ async function projectRemovalTrail(cwd, query) {
|
|
|
52676
52774
|
async function detectMemoryStoreUnreadable(cwd) {
|
|
52677
52775
|
const root = memoryRoot(cwd);
|
|
52678
52776
|
for (const { folder } of MEMORY_TYPES) {
|
|
52679
|
-
const dir =
|
|
52777
|
+
const dir = join4(root, folder);
|
|
52680
52778
|
try {
|
|
52681
52779
|
await readdir21(dir);
|
|
52682
52780
|
} catch (error) {
|
|
@@ -52690,7 +52788,7 @@ async function detectMemoryStoreUnreadable(cwd) {
|
|
|
52690
52788
|
return null;
|
|
52691
52789
|
}
|
|
52692
52790
|
function confineToSkills(cwd, candidate) {
|
|
52693
|
-
const skillsRoot =
|
|
52791
|
+
const skillsRoot = join4(cwd, ".metaproject", "skills", "gdskills");
|
|
52694
52792
|
const target = resolve3(cwd, candidate);
|
|
52695
52793
|
const rel = relative2(skillsRoot, target);
|
|
52696
52794
|
if (rel === "") {
|
|
@@ -52705,7 +52803,7 @@ async function parseCatalogSummaries(cwd) {
|
|
|
52705
52803
|
const summaries = new Map;
|
|
52706
52804
|
let content;
|
|
52707
52805
|
try {
|
|
52708
|
-
const bytes = await readContainedFile(
|
|
52806
|
+
const bytes = await readContainedFile(join4(cwd, ".metaproject", "skills"), join4(cwd, ".metaproject", "skills", "catalog.md"), { maxBytes: 512 * 1024, requireRegularFile: true });
|
|
52709
52807
|
content = bytes.toString("utf8");
|
|
52710
52808
|
} catch {
|
|
52711
52809
|
return summaries;
|
|
@@ -52726,7 +52824,7 @@ async function parseCatalogSummaries(cwd) {
|
|
|
52726
52824
|
return summaries;
|
|
52727
52825
|
}
|
|
52728
52826
|
async function walkSkillCatalog(cwd) {
|
|
52729
|
-
const root =
|
|
52827
|
+
const root = join4(cwd, ".metaproject", "skills", "gdskills");
|
|
52730
52828
|
const entries = [];
|
|
52731
52829
|
const rootInfo = await lstat8(root).catch(() => null);
|
|
52732
52830
|
if (!rootInfo || !rootInfo.isDirectory() || rootInfo.isSymbolicLink())
|
|
@@ -52744,7 +52842,7 @@ async function walkSkillCatalog(cwd) {
|
|
|
52744
52842
|
for (const categoryDir of categoryDirs) {
|
|
52745
52843
|
if (!categoryDir.isDirectory() && !categoryDir.isSymbolicLink())
|
|
52746
52844
|
continue;
|
|
52747
|
-
const categoryPath =
|
|
52845
|
+
const categoryPath = join4(root, categoryDir.name);
|
|
52748
52846
|
const categoryReal = await realpath11(categoryPath).catch(() => null);
|
|
52749
52847
|
const categoryInfo = await stat15(categoryPath).catch(() => null);
|
|
52750
52848
|
if (!categoryReal || !categoryInfo?.isDirectory() || !isPathInside(rootReal, categoryReal))
|
|
@@ -52756,12 +52854,12 @@ async function walkSkillCatalog(cwd) {
|
|
|
52756
52854
|
continue;
|
|
52757
52855
|
}
|
|
52758
52856
|
for (const skillDir of skillDirs) {
|
|
52759
|
-
const skillPath =
|
|
52857
|
+
const skillPath = join4(categoryPath, skillDir.name);
|
|
52760
52858
|
const skillReal = await realpath11(skillPath).catch(() => null);
|
|
52761
52859
|
const skillInfo = await stat15(skillPath).catch(() => null);
|
|
52762
52860
|
if (!skillReal || !skillInfo?.isDirectory() || !isPathInside(rootReal, skillReal))
|
|
52763
52861
|
continue;
|
|
52764
|
-
const skillMdPath =
|
|
52862
|
+
const skillMdPath = join4(skillPath, "SKILL.md");
|
|
52765
52863
|
let content;
|
|
52766
52864
|
try {
|
|
52767
52865
|
const bytes = await readContainedFile(root, skillMdPath, { maxBytes: 512 * 1024, requireRegularFile: true });
|
|
@@ -53027,7 +53125,7 @@ function createMetaprojectAdapter(cwd, overrides = {}) {
|
|
|
53027
53125
|
exists = false;
|
|
53028
53126
|
}
|
|
53029
53127
|
if (!exists) {
|
|
53030
|
-
const relativePath = toPosix(relative2(
|
|
53128
|
+
const relativePath = toPosix(relative2(join4(cwd, ".metaproject", "wiki"), target));
|
|
53031
53129
|
const registry = await readSectionRegistryState(cwd);
|
|
53032
53130
|
if (registry.state === "unreadable") {
|
|
53033
53131
|
return {
|
|
@@ -53068,7 +53166,7 @@ function createMetaprojectAdapter(cwd, overrides = {}) {
|
|
|
53068
53166
|
};
|
|
53069
53167
|
}
|
|
53070
53168
|
try {
|
|
53071
|
-
const content = (await readContainedFile(
|
|
53169
|
+
const content = (await readContainedFile(join4(cwd, ".metaproject", "wiki"), target, {
|
|
53072
53170
|
maxBytes: 8 * 1024 * 1024,
|
|
53073
53171
|
requireRegularFile: true
|
|
53074
53172
|
})).toString("utf8");
|
|
@@ -53112,7 +53210,7 @@ function createMetaprojectAdapter(cwd, overrides = {}) {
|
|
|
53112
53210
|
}
|
|
53113
53211
|
let hasWikiIndex;
|
|
53114
53212
|
try {
|
|
53115
|
-
await readFile60(
|
|
53213
|
+
await readFile60(join4(cwd, ".metaproject", "wiki", "index.md"), "utf8");
|
|
53116
53214
|
hasWikiIndex = true;
|
|
53117
53215
|
} catch {
|
|
53118
53216
|
hasWikiIndex = false;
|
|
@@ -53387,7 +53485,7 @@ function createMetaprojectAdapter(cwd, overrides = {}) {
|
|
|
53387
53485
|
const byName = catalog.find((entry) => entry.name === input.name);
|
|
53388
53486
|
if (byName !== undefined) {
|
|
53389
53487
|
try {
|
|
53390
|
-
const content = (await readContainedFile(
|
|
53488
|
+
const content = (await readContainedFile(join4(cwd, ".metaproject", "skills", "gdskills"), join4(cwd, byName.path), {
|
|
53391
53489
|
maxBytes: 512 * 1024,
|
|
53392
53490
|
requireRegularFile: true
|
|
53393
53491
|
})).toString("utf8");
|
|
@@ -53400,12 +53498,12 @@ function createMetaprojectAdapter(cwd, overrides = {}) {
|
|
|
53400
53498
|
if (confined === null) {
|
|
53401
53499
|
return { name: input.name, path: "", content: "", found: false };
|
|
53402
53500
|
}
|
|
53403
|
-
const byPath = catalog.find((entry) =>
|
|
53501
|
+
const byPath = catalog.find((entry) => join4(cwd, entry.path) === confined);
|
|
53404
53502
|
if (byPath === undefined) {
|
|
53405
53503
|
return { name: input.name, path: "", content: "", found: false };
|
|
53406
53504
|
}
|
|
53407
53505
|
try {
|
|
53408
|
-
const content = (await readContainedFile(
|
|
53506
|
+
const content = (await readContainedFile(join4(cwd, ".metaproject", "skills", "gdskills"), confined, {
|
|
53409
53507
|
maxBytes: 512 * 1024,
|
|
53410
53508
|
requireRegularFile: true
|
|
53411
53509
|
})).toString("utf8");
|
|
@@ -112748,7 +112846,7 @@ var init_jev_rules = __esm(() => {
|
|
|
112748
112846
|
|
|
112749
112847
|
// src/commands/review-jev-rules.ts
|
|
112750
112848
|
import { readFile as readFile112, readdir as readdir41, stat as stat25 } from "fs/promises";
|
|
112751
|
-
import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute3, join as
|
|
112849
|
+
import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute3, join as join5, relative as relative3 } from "path";
|
|
112752
112850
|
function rejectUnknownJevRulesFlags(args) {
|
|
112753
112851
|
const unknown = args.filter((arg) => arg.startsWith("--") && !JEV_RULES_FLAGS.includes(arg.split("=")[0]));
|
|
112754
112852
|
if (unknown.length > 0) {
|
|
@@ -112790,7 +112888,7 @@ async function walkMatching(root, suffixes) {
|
|
|
112790
112888
|
return;
|
|
112791
112889
|
}
|
|
112792
112890
|
for (const entry of entries) {
|
|
112793
|
-
const full =
|
|
112891
|
+
const full = join5(dir, entry.name);
|
|
112794
112892
|
if (entry.isDirectory()) {
|
|
112795
112893
|
await walk(full);
|
|
112796
112894
|
continue;
|
|
@@ -112818,7 +112916,7 @@ function stripKeryxManagedBlock(text) {
|
|
|
112818
112916
|
}
|
|
112819
112917
|
async function discoverRuleSources(cwd, explicitPaths) {
|
|
112820
112918
|
const discovered = [];
|
|
112821
|
-
for (const root of [
|
|
112919
|
+
for (const root of [join5(cwd, ".metaproject", "rules"), join5(cwd, "rules"), join5(cwd, ".claude", "rules")]) {
|
|
112822
112920
|
for (const file of await walkMatching(root, [".md", ".mdc"])) {
|
|
112823
112921
|
const text = await readIfExists(file);
|
|
112824
112922
|
if (text === undefined)
|
|
@@ -112827,7 +112925,7 @@ async function discoverRuleSources(cwd, explicitPaths) {
|
|
|
112827
112925
|
}
|
|
112828
112926
|
}
|
|
112829
112927
|
for (const name of ["CLAUDE.md", "AGENTS.md"]) {
|
|
112830
|
-
const text = await readIfExists(
|
|
112928
|
+
const text = await readIfExists(join5(cwd, name));
|
|
112831
112929
|
if (text === undefined)
|
|
112832
112930
|
continue;
|
|
112833
112931
|
const body = stripKeryxManagedBlock(text);
|
|
@@ -112836,8 +112934,8 @@ async function discoverRuleSources(cwd, explicitPaths) {
|
|
|
112836
112934
|
break;
|
|
112837
112935
|
}
|
|
112838
112936
|
const skillRoots = [
|
|
112839
|
-
[
|
|
112840
|
-
[
|
|
112937
|
+
[join5(cwd, ".metaproject", "project-skills"), "project-skill"],
|
|
112938
|
+
[join5(cwd, ".metaproject", "skills", "gdskills"), "gdskill"]
|
|
112841
112939
|
];
|
|
112842
112940
|
for (const [root, kind] of skillRoots) {
|
|
112843
112941
|
for (const skillMd of await walkMatching(root, ["SKILL.md"])) {
|
|
@@ -112862,7 +112960,7 @@ async function discoverRuleSources(cwd, explicitPaths) {
|
|
|
112862
112960
|
const explicitFiles = [];
|
|
112863
112961
|
const explicitDirSources = [];
|
|
112864
112962
|
for (const raw of explicitPaths) {
|
|
112865
|
-
const resolved = isAbsolute3(raw) ? raw :
|
|
112963
|
+
const resolved = isAbsolute3(raw) ? raw : join5(cwd, raw);
|
|
112866
112964
|
const stats = await stat25(resolved).catch(() => {
|
|
112867
112965
|
return;
|
|
112868
112966
|
});
|
|
@@ -112905,11 +113003,11 @@ async function discoverRuleSources(cwd, explicitPaths) {
|
|
|
112905
113003
|
return { sources: [...byPath.values()].sort((a, b) => a.path.localeCompare(b.path)), excluded: excluded.sort((a, b) => a.path.localeCompare(b.path)) };
|
|
112906
113004
|
}
|
|
112907
113005
|
async function fixturePrPort(dir) {
|
|
112908
|
-
const raw = await readFile112(
|
|
113006
|
+
const raw = await readFile112(join5(dir, "pr.json"), "utf8");
|
|
112909
113007
|
return createFixtureConformPrPort({ pr: JSON.parse(raw) });
|
|
112910
113008
|
}
|
|
112911
113009
|
async function fixtureJevFetch(dir) {
|
|
112912
|
-
const raw = await readFile112(
|
|
113010
|
+
const raw = await readFile112(join5(dir, "jev-responses.json"), "utf8");
|
|
112913
113011
|
const responses = JSON.parse(raw);
|
|
112914
113012
|
let index = 0;
|
|
112915
113013
|
const fn = async () => {
|
|
@@ -115269,7 +115367,7 @@ var init_jev_scenarios = __esm(() => {
|
|
|
115269
115367
|
|
|
115270
115368
|
// src/commands/review-jev-scenarios.ts
|
|
115271
115369
|
import { readFile as readFile121, readdir as readdir43 } from "fs/promises";
|
|
115272
|
-
import { join as
|
|
115370
|
+
import { join as join6, relative as relative4 } from "path";
|
|
115273
115371
|
function symbolsByPathFromRegions(regions) {
|
|
115274
115372
|
const byPath = new Map;
|
|
115275
115373
|
for (const region of regions) {
|
|
@@ -115322,7 +115420,7 @@ async function walkMarkdown2(root) {
|
|
|
115322
115420
|
return;
|
|
115323
115421
|
}
|
|
115324
115422
|
for (const entry of entries) {
|
|
115325
|
-
const full =
|
|
115423
|
+
const full = join6(dir, entry.name);
|
|
115326
115424
|
if (entry.isDirectory()) {
|
|
115327
115425
|
await walk(full);
|
|
115328
115426
|
continue;
|
|
@@ -115336,19 +115434,19 @@ async function walkMarkdown2(root) {
|
|
|
115336
115434
|
}
|
|
115337
115435
|
async function discoverScenarioSources(cwd) {
|
|
115338
115436
|
const scenarios = [];
|
|
115339
|
-
for (const file of await walkMarkdown2(
|
|
115437
|
+
for (const file of await walkMarkdown2(join6(cwd, ".metaproject", "wiki", "user-scenarios"))) {
|
|
115340
115438
|
const text = await readIfExists2(file);
|
|
115341
115439
|
if (text === undefined)
|
|
115342
115440
|
continue;
|
|
115343
115441
|
scenarios.push(scenarioFromWikiPage(relative4(cwd, file), text));
|
|
115344
115442
|
}
|
|
115345
|
-
for (const file of await walkMarkdown2(
|
|
115443
|
+
for (const file of await walkMarkdown2(join6(cwd, "docs", "requirements"))) {
|
|
115346
115444
|
const text = await readIfExists2(file);
|
|
115347
115445
|
if (text === undefined)
|
|
115348
115446
|
continue;
|
|
115349
115447
|
scenarios.push(...scenariosFromPrd(relative4(cwd, file), text));
|
|
115350
115448
|
}
|
|
115351
|
-
const readmeLikeFiles = [
|
|
115449
|
+
const readmeLikeFiles = [join6(cwd, "README.md"), ...await walkMarkdown2(join6(cwd, "docs", "docs"))];
|
|
115352
115450
|
for (const file of readmeLikeFiles) {
|
|
115353
115451
|
const text = await readIfExists2(file);
|
|
115354
115452
|
if (text === undefined)
|
|
@@ -115358,11 +115456,11 @@ async function discoverScenarioSources(cwd) {
|
|
|
115358
115456
|
return scenarios;
|
|
115359
115457
|
}
|
|
115360
115458
|
async function fixturePrPort4(dir) {
|
|
115361
|
-
const raw = await readFile121(
|
|
115459
|
+
const raw = await readFile121(join6(dir, "pr.json"), "utf8");
|
|
115362
115460
|
return createFixtureConformPrPort({ pr: JSON.parse(raw) });
|
|
115363
115461
|
}
|
|
115364
115462
|
async function fixtureJevFetch5(dir) {
|
|
115365
|
-
const raw = await readFile121(
|
|
115463
|
+
const raw = await readFile121(join6(dir, "jev-responses.json"), "utf8");
|
|
115366
115464
|
const responses = JSON.parse(raw);
|
|
115367
115465
|
let index = 0;
|
|
115368
115466
|
const fn = async () => {
|
|
@@ -115987,7 +116085,7 @@ var init_jev_docs = __esm(() => {
|
|
|
115987
116085
|
|
|
115988
116086
|
// src/commands/review-jev-docs.ts
|
|
115989
116087
|
import { readFile as readFile123, readdir as readdir44 } from "fs/promises";
|
|
115990
|
-
import { join as
|
|
116088
|
+
import { join as join7, relative as relative5 } from "path";
|
|
115991
116089
|
function messageOf4(error) {
|
|
115992
116090
|
return error instanceof Error ? error.message : String(error);
|
|
115993
116091
|
}
|
|
@@ -116049,7 +116147,7 @@ async function walkMatching2(root, suffixes) {
|
|
|
116049
116147
|
return;
|
|
116050
116148
|
}
|
|
116051
116149
|
for (const entry of entries) {
|
|
116052
|
-
const full =
|
|
116150
|
+
const full = join7(dir, entry.name);
|
|
116053
116151
|
if (entry.isDirectory()) {
|
|
116054
116152
|
await walk(full);
|
|
116055
116153
|
continue;
|
|
@@ -116109,7 +116207,7 @@ async function walkAllDocFiles(dir) {
|
|
|
116109
116207
|
return out;
|
|
116110
116208
|
}
|
|
116111
116209
|
for (const entry of entries) {
|
|
116112
|
-
const full =
|
|
116210
|
+
const full = join7(dir, entry.name);
|
|
116113
116211
|
if (entry.isDirectory()) {
|
|
116114
116212
|
if (INCLUDE_WALK_PRUNE_DIRS.has(entry.name))
|
|
116115
116213
|
continue;
|
|
@@ -116123,19 +116221,19 @@ async function walkAllDocFiles(dir) {
|
|
|
116123
116221
|
async function resolveIncludeGlob(cwd, glob) {
|
|
116124
116222
|
const rootDir = includeGlobRootDir(glob);
|
|
116125
116223
|
const regex = includeGlobToRegExp(glob);
|
|
116126
|
-
const candidates = await walkAllDocFiles(
|
|
116224
|
+
const candidates = await walkAllDocFiles(join7(cwd, rootDir));
|
|
116127
116225
|
return candidates.filter((file) => regex.test(relative5(cwd, file)));
|
|
116128
116226
|
}
|
|
116129
116227
|
async function discoverDocFiles(cwd, includeGlobs = []) {
|
|
116130
116228
|
const files = new Set;
|
|
116131
|
-
for (const file of await walkMatching2(
|
|
116229
|
+
for (const file of await walkMatching2(join7(cwd, "docs"), [".md"]))
|
|
116132
116230
|
files.add(file);
|
|
116133
116231
|
for (const name of await matchingFileNames(cwd, /^readme/i)) {
|
|
116134
116232
|
if (/^changelog/i.test(name))
|
|
116135
116233
|
continue;
|
|
116136
|
-
files.add(
|
|
116234
|
+
files.add(join7(cwd, name));
|
|
116137
116235
|
}
|
|
116138
|
-
for (const file of await walkMatching2(
|
|
116236
|
+
for (const file of await walkMatching2(join7(cwd, ".metaproject", "wiki"), [".md"]))
|
|
116139
116237
|
files.add(file);
|
|
116140
116238
|
for (const glob of includeGlobs) {
|
|
116141
116239
|
for (const file of await resolveIncludeGlob(cwd, glob))
|
|
@@ -116163,11 +116261,11 @@ function changedCommandNamesFromRegions(regions) {
|
|
|
116163
116261
|
return names;
|
|
116164
116262
|
}
|
|
116165
116263
|
async function fixturePrPort5(dir) {
|
|
116166
|
-
const raw = await readFile123(
|
|
116264
|
+
const raw = await readFile123(join7(dir, "pr.json"), "utf8");
|
|
116167
116265
|
return createFixtureConformPrPort({ pr: JSON.parse(raw) });
|
|
116168
116266
|
}
|
|
116169
116267
|
async function fixtureJevFetch6(dir) {
|
|
116170
|
-
const raw = await readFile123(
|
|
116268
|
+
const raw = await readFile123(join7(dir, "jev-responses.json"), "utf8");
|
|
116171
116269
|
const responses = JSON.parse(raw);
|
|
116172
116270
|
let index = 0;
|
|
116173
116271
|
const fn = async () => {
|
|
@@ -116585,7 +116683,7 @@ var init_jev_comments = __esm(() => {
|
|
|
116585
116683
|
|
|
116586
116684
|
// src/commands/review-jev-comments.ts
|
|
116587
116685
|
import { readFile as readFile125 } from "fs/promises";
|
|
116588
|
-
import { join as
|
|
116686
|
+
import { join as join8 } from "path";
|
|
116589
116687
|
function rejectUnknownJevCommentsFlags(args) {
|
|
116590
116688
|
const unknown = args.filter((arg) => arg.startsWith("--") && !JEV_COMMENTS_FLAGS.includes(arg.split("=")[0]));
|
|
116591
116689
|
if (unknown.length > 0) {
|
|
@@ -116671,15 +116769,15 @@ function createFixtureJevCommentsFactsPort(facts) {
|
|
|
116671
116769
|
};
|
|
116672
116770
|
}
|
|
116673
116771
|
async function fixturePrPort6(dir) {
|
|
116674
|
-
const raw = await readFile125(
|
|
116772
|
+
const raw = await readFile125(join8(dir, "pr.json"), "utf8");
|
|
116675
116773
|
return createFixtureConformPrPort({ pr: JSON.parse(raw) });
|
|
116676
116774
|
}
|
|
116677
116775
|
async function fixtureFactsPort(dir) {
|
|
116678
|
-
const raw = await readFile125(
|
|
116776
|
+
const raw = await readFile125(join8(dir, "git-facts.json"), "utf8").catch(() => "{}");
|
|
116679
116777
|
return createFixtureJevCommentsFactsPort(JSON.parse(raw));
|
|
116680
116778
|
}
|
|
116681
116779
|
async function fixtureJevFetch7(dir) {
|
|
116682
|
-
const raw = await readFile125(
|
|
116780
|
+
const raw = await readFile125(join8(dir, "jev-responses.json"), "utf8");
|
|
116683
116781
|
const responses = JSON.parse(raw);
|
|
116684
116782
|
let index = 0;
|
|
116685
116783
|
const fn = async () => {
|
|
@@ -116693,7 +116791,7 @@ async function fixtureJevFetch7(dir) {
|
|
|
116693
116791
|
return fn;
|
|
116694
116792
|
}
|
|
116695
116793
|
function advisoryLabelsPath(cwd, repo, number) {
|
|
116696
|
-
return
|
|
116794
|
+
return join8(cwd, ".metaproject", "data", "review-jev-comments", `labels__${repo.replace(/\//g, "__")}__${number}.json`);
|
|
116697
116795
|
}
|
|
116698
116796
|
async function readCommentAdvisoryLabels(cwd, repo, number) {
|
|
116699
116797
|
const file = advisoryLabelsPath(cwd, repo, number);
|
|
@@ -127961,7 +128059,7 @@ var init_narrate = __esm(() => {
|
|
|
127961
128059
|
// src/commands/memory.ts
|
|
127962
128060
|
import { randomUUID as randomUUID34 } from "crypto";
|
|
127963
128061
|
import { readdir as readdir45 } from "fs/promises";
|
|
127964
|
-
import { join as
|
|
128062
|
+
import { join as join9 } from "path";
|
|
127965
128063
|
function getService() {
|
|
127966
128064
|
service4 ??= createMemoryService();
|
|
127967
128065
|
return service4;
|
|
@@ -128068,7 +128166,7 @@ async function runIndex(args) {
|
|
|
128068
128166
|
async function detectMemoryStoreUnreadable2(cwd) {
|
|
128069
128167
|
const root = memoryRoot(cwd);
|
|
128070
128168
|
for (const { folder } of MEMORY_TYPES) {
|
|
128071
|
-
const dir =
|
|
128169
|
+
const dir = join9(root, folder);
|
|
128072
128170
|
try {
|
|
128073
128171
|
await readdir45(dir);
|
|
128074
128172
|
} catch (error) {
|
|
@@ -152693,7 +152791,7 @@ function referencesHash(entry) {
|
|
|
152693
152791
|
}
|
|
152694
152792
|
return hash.digest("hex");
|
|
152695
152793
|
}
|
|
152696
|
-
function
|
|
152794
|
+
function loadCache2(cachePath) {
|
|
152697
152795
|
if (!existsSync51(cachePath))
|
|
152698
152796
|
return {};
|
|
152699
152797
|
try {
|
|
@@ -152821,7 +152919,7 @@ async function runStocktake(root, options = {}) {
|
|
|
152821
152919
|
const now = options.now ?? (() => new Date);
|
|
152822
152920
|
const { entries: catalog, unreadable } = loadSkillCatalogWithDiagnostics(root, { scope });
|
|
152823
152921
|
const cachePath = options.cachePath ?? path295.join(root, ".metaproject", "data", "skills", "stocktake", "cache.json");
|
|
152824
|
-
const cache =
|
|
152922
|
+
const cache = loadCache2(cachePath);
|
|
152825
152923
|
const fingerprint = catalogFingerprint(catalog);
|
|
152826
152924
|
let hits = 0;
|
|
152827
152925
|
let misses = 0;
|
|
@@ -159572,7 +159670,7 @@ var init_post = __esm(() => {
|
|
|
159572
159670
|
|
|
159573
159671
|
// src/commands/review-bot.ts
|
|
159574
159672
|
import { readFile as readFile158 } from "fs/promises";
|
|
159575
|
-
import { join as
|
|
159673
|
+
import { join as join10 } from "path";
|
|
159576
159674
|
function reject(args, valued, boolean, usage) {
|
|
159577
159675
|
const problems = [];
|
|
159578
159676
|
for (let index = 0;index < args.length; index += 1) {
|
|
@@ -159601,7 +159699,7 @@ async function portFor(args) {
|
|
|
159601
159699
|
return createGhPort();
|
|
159602
159700
|
let pull;
|
|
159603
159701
|
try {
|
|
159604
|
-
pull = JSON.parse(await readFile158(
|
|
159702
|
+
pull = JSON.parse(await readFile158(join10(fixtures, "pull.json"), "utf8"));
|
|
159605
159703
|
} catch {
|
|
159606
159704
|
pull = {};
|
|
159607
159705
|
}
|
|
@@ -161041,7 +161139,7 @@ var init_floor = __esm(() => {
|
|
|
161041
161139
|
|
|
161042
161140
|
// src/commands/review.ts
|
|
161043
161141
|
import { mkdir as mkdir66, readdir as readdir58, readFile as readFile162 } from "fs/promises";
|
|
161044
|
-
import path317, { join as
|
|
161142
|
+
import path317, { join as join11 } from "path";
|
|
161045
161143
|
function reviewerList(args) {
|
|
161046
161144
|
return (optionValue(args, "--reviewers") ?? "").split(",").map((item) => item.trim()).filter(Boolean);
|
|
161047
161145
|
}
|
|
@@ -161716,7 +161814,7 @@ async function resolvePort(args) {
|
|
|
161716
161814
|
}
|
|
161717
161815
|
const files = {};
|
|
161718
161816
|
for (const key of ["pull", "pull-comments", "pull-reviews", "issue-comments"]) {
|
|
161719
|
-
const file =
|
|
161817
|
+
const file = join11(fixtures, `${key}.json`);
|
|
161720
161818
|
try {
|
|
161721
161819
|
files[key] = JSON.parse(await readFile162(file, "utf8"));
|
|
161722
161820
|
} catch {
|
|
@@ -161726,13 +161824,13 @@ async function resolvePort(args) {
|
|
|
161726
161824
|
return createFixturePort(files);
|
|
161727
161825
|
}
|
|
161728
161826
|
async function fixtureCiPort(dir) {
|
|
161729
|
-
const runInfo = JSON.parse(await readFile162(
|
|
161730
|
-
const log = await readFile162(
|
|
161731
|
-
const history = await readFile162(
|
|
161732
|
-
const attempts = await readFile162(
|
|
161733
|
-
const changedFiles = await readFile162(
|
|
161734
|
-
const runsByHeadSha = await readFile162(
|
|
161735
|
-
const related = await readFile162(
|
|
161827
|
+
const runInfo = JSON.parse(await readFile162(join11(dir, "ci-run-info.json"), "utf8"));
|
|
161828
|
+
const log = await readFile162(join11(dir, "ci-failed-log.txt"), "utf8").catch(() => "");
|
|
161829
|
+
const history = await readFile162(join11(dir, "ci-history.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => ({}));
|
|
161830
|
+
const attempts = await readFile162(join11(dir, "ci-attempts.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => ({}));
|
|
161831
|
+
const changedFiles = await readFile162(join11(dir, "ci-changed-files.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => ({}));
|
|
161832
|
+
const runsByHeadSha = await readFile162(join11(dir, "ci-runs-by-head-sha.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => ({}));
|
|
161833
|
+
const related = await readFile162(join11(dir, "ci-related-runs.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => ({}));
|
|
161736
161834
|
return createFixtureCiPort({
|
|
161737
161835
|
runs: { [runInfo.runId]: runInfo, ...related.runs },
|
|
161738
161836
|
logs: { [runInfo.runId]: log, ...related.logs },
|
|
@@ -161743,7 +161841,7 @@ async function fixtureCiPort(dir) {
|
|
|
161743
161841
|
});
|
|
161744
161842
|
}
|
|
161745
161843
|
async function fixtureJevFetch9(dir) {
|
|
161746
|
-
const body = await readFile162(
|
|
161844
|
+
const body = await readFile162(join11(dir, "jev-response.json"), "utf8");
|
|
161747
161845
|
const fn = async () => new Response(body, { status: 200, headers: { "content-type": "application/json" } });
|
|
161748
161846
|
return fn;
|
|
161749
161847
|
}
|
|
@@ -161912,12 +162010,12 @@ async function runCiTriageEval(cwd, args, evalFile) {
|
|
|
161912
162010
|
}
|
|
161913
162011
|
}
|
|
161914
162012
|
async function fixtureConformJevFetch(dir) {
|
|
161915
|
-
const body = await readFile162(
|
|
162013
|
+
const body = await readFile162(join11(dir, "jev-response.json"), "utf8");
|
|
161916
162014
|
const fn = async () => new Response(body, { status: 200, headers: { "content-type": "application/json" } });
|
|
161917
162015
|
return fn;
|
|
161918
162016
|
}
|
|
161919
162017
|
async function fixtureConformPrPortFrom(dir) {
|
|
161920
|
-
const pr = JSON.parse(await readFile162(
|
|
162018
|
+
const pr = JSON.parse(await readFile162(join11(dir, "pr.json"), "utf8"));
|
|
161921
162019
|
return createFixtureConformPrPort({ pr });
|
|
161922
162020
|
}
|
|
161923
162021
|
function accumulateJevUsage(acc, usage) {
|
|
@@ -161998,7 +162096,7 @@ async function explainConformVerdicts(cwd, refPath, verdicts, threshold, fixture
|
|
|
161998
162096
|
return {};
|
|
161999
162097
|
if (fixturesDir !== undefined) {
|
|
162000
162098
|
try {
|
|
162001
|
-
return JSON.parse(await readFile162(
|
|
162099
|
+
return JSON.parse(await readFile162(join11(fixturesDir, "explain-response.json"), "utf8"));
|
|
162002
162100
|
} catch {
|
|
162003
162101
|
return {};
|
|
162004
162102
|
}
|
|
@@ -162046,7 +162144,7 @@ function parsePositiveIntFlag(args, flag, fallback) {
|
|
|
162046
162144
|
}
|
|
162047
162145
|
async function readReportFindings2(reportDir) {
|
|
162048
162146
|
try {
|
|
162049
|
-
const raw = JSON.parse(await readFile162(
|
|
162147
|
+
const raw = JSON.parse(await readFile162(join11(reportDir, "findings.json"), "utf8"));
|
|
162050
162148
|
return Array.isArray(raw) ? raw : [];
|
|
162051
162149
|
} catch {
|
|
162052
162150
|
return [];
|
|
@@ -162118,7 +162216,7 @@ async function runConform(args) {
|
|
|
162118
162216
|
const fetchFn = fixturesDir === undefined ? globalThis.fetch : await fixtureConformJevFetch(fixturesDir);
|
|
162119
162217
|
const acc = { jevCalls: 0, inputTokens: 0, outputTokens: 0, costUsd: 0, sawUsage: false };
|
|
162120
162218
|
const clauses = await resolveConformClauseTags(cwd, refPath, docText, rawClauses, fetchFn, model, acc);
|
|
162121
|
-
await writeFileAtomic(
|
|
162219
|
+
await writeFileAtomic(join11(cwd, CONFORM_RECENTS_PATH), `${JSON.stringify(withRecentDoc(await readRecentConformDocs2(cwd), refPath), null, 2)}
|
|
162122
162220
|
`, { mode: 384 }).catch(() => {});
|
|
162123
162221
|
const notCheckable = clauses.filter((c) => !c.checkable);
|
|
162124
162222
|
const checkable = clauses.filter((c) => c.checkable);
|
|
@@ -162150,7 +162248,7 @@ async function runConform(args) {
|
|
|
162150
162248
|
hunkTotalRegions = hunkResult.totalRegions;
|
|
162151
162249
|
} else if (reportDir !== undefined) {
|
|
162152
162250
|
target = { kind: "report", label: reportDir };
|
|
162153
|
-
const reportMarkdown = await readFile162(
|
|
162251
|
+
const reportMarkdown = await readFile162(join11(reportDir, "report.md"), "utf8").catch(() => "");
|
|
162154
162252
|
const findings = await readReportFindings2(reportDir);
|
|
162155
162253
|
const facts = computeReportConformFacts(reportMarkdown, findings);
|
|
162156
162254
|
const redacted = reportRedactedStateText(reportMarkdown);
|
|
@@ -162191,7 +162289,7 @@ async function runConform(args) {
|
|
|
162191
162289
|
}
|
|
162192
162290
|
async function readRecentConformDocs2(cwd) {
|
|
162193
162291
|
try {
|
|
162194
|
-
const raw = JSON.parse(await readFile162(
|
|
162292
|
+
const raw = JSON.parse(await readFile162(join11(cwd, CONFORM_RECENTS_PATH), "utf8"));
|
|
162195
162293
|
return Array.isArray(raw) ? raw : [];
|
|
162196
162294
|
} catch {
|
|
162197
162295
|
return [];
|
|
@@ -162440,7 +162538,7 @@ async function runStack(args) {
|
|
|
162440
162538
|
console.log(renderStackScopingMarkdown(detected, decisions));
|
|
162441
162539
|
}
|
|
162442
162540
|
async function stackScopingForInstalledReviewers(cwd, detected) {
|
|
162443
|
-
const reviewRoot =
|
|
162541
|
+
const reviewRoot = join11(cwd, ".metaproject", "skills", "gdskills", "review");
|
|
162444
162542
|
let entries;
|
|
162445
162543
|
try {
|
|
162446
162544
|
entries = await readdir58(reviewRoot, { withFileTypes: true });
|
|
@@ -162452,7 +162550,7 @@ async function stackScopingForInstalledReviewers(cwd, detected) {
|
|
|
162452
162550
|
if (!entry.isDirectory()) {
|
|
162453
162551
|
continue;
|
|
162454
162552
|
}
|
|
162455
|
-
const skillMdPath =
|
|
162553
|
+
const skillMdPath = join11(reviewRoot, entry.name, "SKILL.md");
|
|
162456
162554
|
let content;
|
|
162457
162555
|
try {
|
|
162458
162556
|
content = await readFile162(skillMdPath, "utf8");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.41",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|