memorix 1.2.0 → 1.2.1
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/CHANGELOG.md +14 -1
- package/README.md +4 -2
- package/README.zh-CN.md +4 -2
- package/dist/cli/index.js +677 -441
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +830 -646
- package/dist/index.js.map +1 -1
- package/dist/maintenance-runner.js +110 -5
- package/dist/maintenance-runner.js.map +1 -1
- package/dist/memcode-runtime/CHANGELOG.md +14 -1
- package/dist/sdk.js +830 -646
- package/dist/sdk.js.map +1 -1
- package/docs/API_REFERENCE.md +3 -1
- package/docs/DEVELOPMENT.md +4 -0
- package/docs/SETUP.md +7 -1
- package/docs/knowledge/workflows/memorix-release.md +57 -0
- package/package.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/src/cli/commands/codegraph.ts +2 -3
- package/src/cli/commands/knowledge.ts +40 -0
- package/src/cli/commands/serve-http.ts +14 -41
- package/src/cli/commands/setup.ts +9 -3
- package/src/codegraph/auto-context.ts +3 -15
- package/src/codegraph/current-facts.ts +19 -1
- package/src/codegraph/task-lens.ts +49 -5
- package/src/dashboard/server.ts +15 -46
- package/src/knowledge/claims.ts +51 -1
- package/src/knowledge/types.ts +1 -0
- package/src/knowledge/workflows.ts +34 -3
- package/src/memory/auto-relations.ts +21 -0
- package/src/memory/graph-scope.ts +46 -0
- package/src/orchestrate/verify-gate.ts +33 -10
- package/src/server.ts +75 -13
package/dist/cli/index.js
CHANGED
|
@@ -3212,7 +3212,7 @@ ${import_picocolors.default.gray(m3)} ${s2}
|
|
|
3212
3212
|
|
|
3213
3213
|
// src/cli/version.ts
|
|
3214
3214
|
function getCliVersion() {
|
|
3215
|
-
return true ? "1.2.
|
|
3215
|
+
return true ? "1.2.1" : pkg.version;
|
|
3216
3216
|
}
|
|
3217
3217
|
var init_version = __esm({
|
|
3218
3218
|
"src/cli/version.ts"() {
|
|
@@ -23372,9 +23372,9 @@ async function detectInstalledAgents() {
|
|
|
23372
23372
|
} catch {
|
|
23373
23373
|
}
|
|
23374
23374
|
try {
|
|
23375
|
-
const { execSync:
|
|
23375
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
23376
23376
|
const whereCmd = process.platform === "win32" ? "where gemini" : "which gemini";
|
|
23377
|
-
|
|
23377
|
+
execSync10(whereCmd, { stdio: "ignore" });
|
|
23378
23378
|
agents.push("gemini-cli");
|
|
23379
23379
|
} catch {
|
|
23380
23380
|
}
|
|
@@ -23907,6 +23907,7 @@ __export(setup_exports, {
|
|
|
23907
23907
|
getMcpAdapter: () => getMcpAdapter,
|
|
23908
23908
|
getSetupAgentTargets: () => getSetupAgentTargets,
|
|
23909
23909
|
getSetupIntegrationRows: () => getSetupIntegrationRows2,
|
|
23910
|
+
installAgentSetup: () => installAgentSetup,
|
|
23910
23911
|
installAntigravityPluginPackage: () => installAntigravityPluginPackage,
|
|
23911
23912
|
installGeminiExtensionPackage: () => installGeminiExtensionPackage,
|
|
23912
23913
|
installHermesPluginPackage: () => installHermesPluginPackage,
|
|
@@ -24738,13 +24739,19 @@ async function installAgentSetup(agent, plan, global2) {
|
|
|
24738
24739
|
} else if (hasOmpPackage) {
|
|
24739
24740
|
v3.info(`${agent}: extension command, hook events, and skills are bundled in the Oh-my-Pi package`);
|
|
24740
24741
|
} else if (hasExtensionPackage) {
|
|
24741
|
-
if (plan.actions.includes("hooks")
|
|
24742
|
+
if (plan.actions.includes("hooks")) {
|
|
24742
24743
|
const result = await installHooks2(agent, targetRoot, global2);
|
|
24743
24744
|
v3.success(`${agent}: integration files -> ${result.configPath}`);
|
|
24745
|
+
} else if (plan.actions.includes("project-guidance")) {
|
|
24746
|
+
const rulesPath = await installAgentGuidance2(agent, targetRoot, global2);
|
|
24747
|
+
v3.success(`${agent}: guidance -> ${rulesPath}`);
|
|
24744
24748
|
}
|
|
24745
|
-
} else if (
|
|
24749
|
+
} else if (plan.actions.includes("hooks")) {
|
|
24746
24750
|
const result = await installHooks2(agent, targetRoot, global2);
|
|
24747
24751
|
v3.success(`${agent}: integration files -> ${result.configPath}`);
|
|
24752
|
+
} else if (plan.actions.includes("project-guidance")) {
|
|
24753
|
+
const rulesPath = await installAgentGuidance2(agent, targetRoot, global2);
|
|
24754
|
+
v3.success(`${agent}: guidance -> ${rulesPath}`);
|
|
24748
24755
|
}
|
|
24749
24756
|
if (agent === "pi") {
|
|
24750
24757
|
v3.info("pi: Pi has no MCP config lane in the current CLI; use the installed package extension and skill.");
|
|
@@ -28205,6 +28212,7 @@ __export(claims_exports, {
|
|
|
28205
28212
|
buildClaimIdentity: () => buildClaimIdentity,
|
|
28206
28213
|
deriveLowRiskClaimsFromObservation: () => deriveLowRiskClaimsFromObservation,
|
|
28207
28214
|
requalifyClaimsForCodeState: () => requalifyClaimsForCodeState,
|
|
28215
|
+
reviewClaim: () => reviewClaim,
|
|
28208
28216
|
selectClaimsForTask: () => selectClaimsForTask,
|
|
28209
28217
|
supersedeClaim: () => supersedeClaim,
|
|
28210
28218
|
writeClaim: () => writeClaim
|
|
@@ -28391,6 +28399,39 @@ function writeClaim(store2, input) {
|
|
|
28391
28399
|
};
|
|
28392
28400
|
});
|
|
28393
28401
|
}
|
|
28402
|
+
function reviewClaim(store2, input) {
|
|
28403
|
+
if (input.reviewState !== "approved" && input.reviewState !== "rejected") {
|
|
28404
|
+
throw new Error("A claim review must approve or reject the claim");
|
|
28405
|
+
}
|
|
28406
|
+
const detail = compactText(input.detail, "review detail");
|
|
28407
|
+
return store2.transaction(() => {
|
|
28408
|
+
const claim = store2.getClaim(input.claimId);
|
|
28409
|
+
if (!claim) throw new Error("Claim was not found");
|
|
28410
|
+
if (input.reviewState === "approved" && claim.status === "superseded") {
|
|
28411
|
+
throw new Error("A superseded claim cannot be approved");
|
|
28412
|
+
}
|
|
28413
|
+
const now3 = (/* @__PURE__ */ new Date()).toISOString();
|
|
28414
|
+
const nextStatus = input.reviewState === "rejected" ? "unknown" : claim.status === "unknown" && claim.reviewState === "rejected" ? "active" : claim.status;
|
|
28415
|
+
const updated = {
|
|
28416
|
+
...claim,
|
|
28417
|
+
status: nextStatus,
|
|
28418
|
+
reviewState: input.reviewState,
|
|
28419
|
+
updatedAt: now3
|
|
28420
|
+
};
|
|
28421
|
+
store2.updateClaim(updated);
|
|
28422
|
+
store2.recordEvent({
|
|
28423
|
+
projectId: claim.projectId,
|
|
28424
|
+
claimId: claim.id,
|
|
28425
|
+
kind: "reviewed",
|
|
28426
|
+
fromStatus: claim.status,
|
|
28427
|
+
toStatus: updated.status,
|
|
28428
|
+
detail: "Review: " + claim.reviewState + " -> " + input.reviewState + ". " + detail,
|
|
28429
|
+
createdAt: now3
|
|
28430
|
+
});
|
|
28431
|
+
reconcileConflicts(store2, claim.projectId, claim.conflictKey, now3);
|
|
28432
|
+
return store2.getClaim(claim.id) ?? updated;
|
|
28433
|
+
});
|
|
28434
|
+
}
|
|
28394
28435
|
function supersedeClaim(store2, input) {
|
|
28395
28436
|
const evidence = validateEvidence(input.evidence);
|
|
28396
28437
|
return store2.transaction(() => {
|
|
@@ -28479,7 +28520,7 @@ function deriveLowRiskClaimsFromObservation(store2, observation, codeStore) {
|
|
|
28479
28520
|
scope: "project",
|
|
28480
28521
|
confidence,
|
|
28481
28522
|
observedAt: observation.updatedAt ?? observation.createdAt,
|
|
28482
|
-
reviewState: "approved",
|
|
28523
|
+
reviewState: isGit ? "approved" : "needs-review",
|
|
28483
28524
|
origin: isGit ? "git" : "derived",
|
|
28484
28525
|
evidence
|
|
28485
28526
|
});
|
|
@@ -32811,6 +32852,350 @@ var init_workflow_sync = __esm({
|
|
|
32811
32852
|
}
|
|
32812
32853
|
});
|
|
32813
32854
|
|
|
32855
|
+
// src/codegraph/task-lens.ts
|
|
32856
|
+
var task_lens_exports = {};
|
|
32857
|
+
__export(task_lens_exports, {
|
|
32858
|
+
containsTaskKeyword: () => containsTaskKeyword,
|
|
32859
|
+
lensPathCandidates: () => lensPathCandidates,
|
|
32860
|
+
lensVerificationHints: () => lensVerificationHints,
|
|
32861
|
+
rankLensPaths: () => rankLensPaths,
|
|
32862
|
+
rankLensSources: () => rankLensSources,
|
|
32863
|
+
resolveTaskLens: () => resolveTaskLens,
|
|
32864
|
+
scoreLensSource: () => scoreLensSource,
|
|
32865
|
+
shouldShowLensSource: () => shouldShowLensSource
|
|
32866
|
+
});
|
|
32867
|
+
function normalizePath2(path34) {
|
|
32868
|
+
return path34.replace(/\\/g, "/");
|
|
32869
|
+
}
|
|
32870
|
+
function tokenize3(text) {
|
|
32871
|
+
return (text.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
|
|
32872
|
+
}
|
|
32873
|
+
function containsTaskKeyword(text, keyword) {
|
|
32874
|
+
const matcher = /^[a-z0-9_-]+$/i.test(keyword) ? new RegExp(`(^|[^a-z0-9_-])${keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?=[^a-z0-9_-]|$)`, "gi") : new RegExp(keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
32875
|
+
let match;
|
|
32876
|
+
while ((match = matcher.exec(text)) !== null) {
|
|
32877
|
+
const keywordIndex = match.index + (match[1]?.length ?? 0);
|
|
32878
|
+
if (!isNegatedTaskKeyword(text, keywordIndex)) return true;
|
|
32879
|
+
}
|
|
32880
|
+
return false;
|
|
32881
|
+
}
|
|
32882
|
+
function isNegatedTaskKeyword(text, keywordIndex) {
|
|
32883
|
+
const boundary = Math.max(
|
|
32884
|
+
text.lastIndexOf(".", keywordIndex - 1),
|
|
32885
|
+
text.lastIndexOf("!", keywordIndex - 1),
|
|
32886
|
+
text.lastIndexOf("?", keywordIndex - 1),
|
|
32887
|
+
text.lastIndexOf(";", keywordIndex - 1),
|
|
32888
|
+
text.lastIndexOf("\n", keywordIndex - 1),
|
|
32889
|
+
text.lastIndexOf("\u3002", keywordIndex - 1),
|
|
32890
|
+
text.lastIndexOf("\uFF01", keywordIndex - 1),
|
|
32891
|
+
text.lastIndexOf("\uFF1F", keywordIndex - 1),
|
|
32892
|
+
text.lastIndexOf("\uFF1B", keywordIndex - 1)
|
|
32893
|
+
);
|
|
32894
|
+
let prefix = text.slice(boundary + 1, keywordIndex).toLowerCase();
|
|
32895
|
+
const contrast = /(?:,|\uff0c)\s*(?:but|however|instead|yet|\u4f46\u662f|\u4f46|\u800c\u662f)\s*/gi;
|
|
32896
|
+
let contrastMatch;
|
|
32897
|
+
let contrastEnd = -1;
|
|
32898
|
+
while ((contrastMatch = contrast.exec(prefix)) !== null) contrastEnd = contrast.lastIndex;
|
|
32899
|
+
if (contrastEnd >= 0) prefix = prefix.slice(contrastEnd);
|
|
32900
|
+
if (/\b(?:do|does|did|should|must|can|could|will|would|may|might)\s+not\b/.test(prefix)) return true;
|
|
32901
|
+
if (/\b(?:don't|dont|never|without|avoid|skip)\b/.test(prefix)) return true;
|
|
32902
|
+
if (/(?:^|[\s,])no\s+(?:[a-z0-9_-]+\s*){0,4}$/i.test(prefix)) return true;
|
|
32903
|
+
const chineseClauseStart = Math.max(prefix.lastIndexOf(","), prefix.lastIndexOf("\uFF0C"), prefix.lastIndexOf("\u3001"));
|
|
32904
|
+
const chineseClause = prefix.slice(chineseClauseStart + 1);
|
|
32905
|
+
return /(?:\u4e0d\u8981|\u4e0d\u5e94|\u4e0d\u53ef|\u4e0d\u80fd|\u4e0d\u4f1a|\u7981\u6b62|\u52ff|\u4e0d)\s*(?:\u7acb\u5373|\u76f4\u63a5|\u518d|\u73b0\u5728|\u64c5\u81ea|\u5148)?\s*$/.test(chineseClause);
|
|
32906
|
+
}
|
|
32907
|
+
function resolveTaskLens(task) {
|
|
32908
|
+
const normalized = (task ?? "").toLowerCase();
|
|
32909
|
+
if (!normalized.trim()) return LENSES.general;
|
|
32910
|
+
let best = {
|
|
32911
|
+
id: "general",
|
|
32912
|
+
score: 0,
|
|
32913
|
+
priority: Number.MAX_SAFE_INTEGER
|
|
32914
|
+
};
|
|
32915
|
+
for (const id of LENS_PRIORITY) {
|
|
32916
|
+
const score = KEYWORDS[id].reduce((sum, keyword) => sum + (containsTaskKeyword(normalized, keyword) ? 1 : 0), 0);
|
|
32917
|
+
const priority = LENS_PRIORITY.indexOf(id);
|
|
32918
|
+
if (score > best.score || score === best.score && score > 0 && priority < best.priority) {
|
|
32919
|
+
best = { id, score, priority };
|
|
32920
|
+
}
|
|
32921
|
+
}
|
|
32922
|
+
return best.score > 0 ? LENSES[best.id] : LENSES.general;
|
|
32923
|
+
}
|
|
32924
|
+
function pathKindScore(path34, lens) {
|
|
32925
|
+
const normalized = normalizePath2(path34).toLowerCase();
|
|
32926
|
+
const name = normalized.split("/").pop() ?? normalized;
|
|
32927
|
+
const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
|
|
32928
|
+
const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
|
|
32929
|
+
const isSource = normalized.startsWith("src/") || normalized.includes("/src/");
|
|
32930
|
+
const isPackage = name === "package.json" || name === "package-lock.json" || name === "pnpm-lock.yaml" || name === "yarn.lock";
|
|
32931
|
+
const isChangelog = name === "changelog.md" || name === "changes.md";
|
|
32932
|
+
const isWorkflow = normalized.startsWith(".github/workflows/");
|
|
32933
|
+
switch (lens.id) {
|
|
32934
|
+
case "bugfix":
|
|
32935
|
+
return (isTest ? 80 : 0) + (isSource ? 50 : 0) + (normalized.includes("debug") ? 20 : 0);
|
|
32936
|
+
case "test":
|
|
32937
|
+
return (isTest ? 90 : 0) + (isSource ? 45 : 0);
|
|
32938
|
+
case "release":
|
|
32939
|
+
return (isChangelog ? 100 : 0) + (isPackage ? 90 : 0) + (isWorkflow ? 70 : 0) + (inDocs ? 35 : 0);
|
|
32940
|
+
case "onboarding":
|
|
32941
|
+
return (name === "readme.md" ? 100 : 0) + (inDocs ? 80 : 0) + (isPackage ? 45 : 0) + (isSource ? 20 : 0);
|
|
32942
|
+
case "docs":
|
|
32943
|
+
return (inDocs ? 100 : 0) + (isChangelog ? 60 : 0) + (isSource ? 25 : 0);
|
|
32944
|
+
case "refactor":
|
|
32945
|
+
return (isSource ? 70 : 0) + (isTest ? 65 : 0);
|
|
32946
|
+
case "feature":
|
|
32947
|
+
return (isSource ? 80 : 0) + (isTest ? 45 : 0) + (inDocs ? 20 : 0);
|
|
32948
|
+
default:
|
|
32949
|
+
if (isSource || isTest) return 60;
|
|
32950
|
+
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 45;
|
|
32951
|
+
if (inDocs) return 20;
|
|
32952
|
+
return 0;
|
|
32953
|
+
}
|
|
32954
|
+
}
|
|
32955
|
+
function tokenScore(text, tokens) {
|
|
32956
|
+
if (tokens.length === 0) return 0;
|
|
32957
|
+
const normalized = text.toLowerCase();
|
|
32958
|
+
return tokens.reduce((sum, token) => sum + (normalized.includes(token) ? 12 : 0), 0);
|
|
32959
|
+
}
|
|
32960
|
+
function sourceTaskMatchScore(source, task) {
|
|
32961
|
+
const tokens = tokenize3(task ?? "");
|
|
32962
|
+
if (tokens.length === 0) return 0;
|
|
32963
|
+
const text = [
|
|
32964
|
+
source.title,
|
|
32965
|
+
source.path ?? "",
|
|
32966
|
+
source.symbol ?? ""
|
|
32967
|
+
].join("\n").toLowerCase();
|
|
32968
|
+
const matches = tokens.filter((token) => text.includes(token)).length;
|
|
32969
|
+
if (matches >= 2) return 40;
|
|
32970
|
+
if (matches === 1) return 24;
|
|
32971
|
+
return 0;
|
|
32972
|
+
}
|
|
32973
|
+
function fallbackPathRank(path34) {
|
|
32974
|
+
const normalized = normalizePath2(path34);
|
|
32975
|
+
if (normalized.startsWith("src/")) return 0;
|
|
32976
|
+
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
|
|
32977
|
+
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
32978
|
+
if (normalized.startsWith("docs/") || normalized.toLowerCase() === "readme.md") return 3;
|
|
32979
|
+
return 4;
|
|
32980
|
+
}
|
|
32981
|
+
function rankLensPaths(paths, lens, task) {
|
|
32982
|
+
const tokens = tokenize3(task ?? "");
|
|
32983
|
+
return [...new Set(paths.map(normalizePath2))].map((path34, index) => ({
|
|
32984
|
+
path: path34,
|
|
32985
|
+
index,
|
|
32986
|
+
score: pathKindScore(path34, lens) + tokenScore(path34, tokens),
|
|
32987
|
+
fallback: fallbackPathRank(path34)
|
|
32988
|
+
})).sort((a3, b3) => b3.score - a3.score || a3.fallback - b3.fallback || a3.index - b3.index || a3.path.localeCompare(b3.path)).map((item) => item.path);
|
|
32989
|
+
}
|
|
32990
|
+
function lensPathCandidates(lens) {
|
|
32991
|
+
switch (lens.id) {
|
|
32992
|
+
case "release":
|
|
32993
|
+
return ["CHANGELOG.md", "package.json", "package-lock.json", ".github/workflows/ci.yml", ".github/workflows/test.yml", "README.md"];
|
|
32994
|
+
case "onboarding":
|
|
32995
|
+
return ["README.md", "docs/README.md", "docs/API_REFERENCE.md", "package.json"];
|
|
32996
|
+
case "docs":
|
|
32997
|
+
return ["README.md", "README.zh-CN.md", "docs/README.md", "docs/API_REFERENCE.md", "CHANGELOG.md"];
|
|
32998
|
+
case "test":
|
|
32999
|
+
case "bugfix":
|
|
33000
|
+
return ["tests", "test"];
|
|
33001
|
+
default:
|
|
33002
|
+
return [];
|
|
33003
|
+
}
|
|
33004
|
+
}
|
|
33005
|
+
function scoreLensSource(source, lens, task) {
|
|
33006
|
+
const tokens = tokenize3(task ?? "");
|
|
33007
|
+
const text = [source.title, source.type, source.path ?? "", source.symbol ?? ""].join("\n");
|
|
33008
|
+
return pathKindScore(source.path ?? "", lens) + tokenScore(text, tokens) + sourceTaskMatchScore(source, task);
|
|
33009
|
+
}
|
|
33010
|
+
function rankLensSources(sources, lens, task) {
|
|
33011
|
+
return [...sources].map((source, index) => ({
|
|
33012
|
+
source,
|
|
33013
|
+
index,
|
|
33014
|
+
score: scoreLensSource(source, lens, task)
|
|
33015
|
+
})).sort((a3, b3) => b3.score - a3.score || a3.source.observationId - b3.source.observationId || a3.index - b3.index).map((item) => item.source);
|
|
33016
|
+
}
|
|
33017
|
+
function lensVerificationHints(lens) {
|
|
33018
|
+
switch (lens.id) {
|
|
33019
|
+
case "bugfix":
|
|
33020
|
+
return [
|
|
33021
|
+
"run the smallest failing test or repro first",
|
|
33022
|
+
"inspect the changed code path before trusting old memory"
|
|
33023
|
+
];
|
|
33024
|
+
case "test":
|
|
33025
|
+
return [
|
|
33026
|
+
"run the exact focused test file or test name first",
|
|
33027
|
+
"inspect fixtures and harness setup before changing assertions"
|
|
33028
|
+
];
|
|
33029
|
+
case "release":
|
|
33030
|
+
return [
|
|
33031
|
+
"run build, tests, package smoke, and publish dry-run where available",
|
|
33032
|
+
"verify package metadata, changelog, and Git state before publishing"
|
|
33033
|
+
];
|
|
33034
|
+
case "onboarding":
|
|
33035
|
+
return [
|
|
33036
|
+
"read the docs/start files first, then inspect only the code paths needed for the task",
|
|
33037
|
+
"treat old implementation memories as leads until current code confirms them"
|
|
33038
|
+
];
|
|
33039
|
+
case "refactor":
|
|
33040
|
+
return [
|
|
33041
|
+
"inspect call sites and tests before editing shared code",
|
|
33042
|
+
"run the narrow affected test plus one regression smoke"
|
|
33043
|
+
];
|
|
33044
|
+
case "docs":
|
|
33045
|
+
return [
|
|
33046
|
+
"check headings, links, commands, and examples against current code",
|
|
33047
|
+
"run the smallest docs or package smoke available"
|
|
33048
|
+
];
|
|
33049
|
+
case "feature":
|
|
33050
|
+
return [
|
|
33051
|
+
"inspect the closest existing implementation pattern before adding new code",
|
|
33052
|
+
"run focused tests plus one user-flow smoke after changes"
|
|
33053
|
+
];
|
|
33054
|
+
default:
|
|
33055
|
+
return [
|
|
33056
|
+
"inspect the Start here files before editing",
|
|
33057
|
+
"run the smallest relevant test or smoke command after changes"
|
|
33058
|
+
];
|
|
33059
|
+
}
|
|
33060
|
+
}
|
|
33061
|
+
function shouldShowLensSource(source, lens, task) {
|
|
33062
|
+
if (lens.id === "general") return true;
|
|
33063
|
+
const score = scoreLensSource(source, lens, task);
|
|
33064
|
+
if (lens.id === "onboarding" || lens.id === "release" || lens.id === "docs") return score >= 40;
|
|
33065
|
+
return score > 0;
|
|
33066
|
+
}
|
|
33067
|
+
var STOP_WORDS, LENSES, KEYWORDS, LENS_PRIORITY;
|
|
33068
|
+
var init_task_lens = __esm({
|
|
33069
|
+
"src/codegraph/task-lens.ts"() {
|
|
33070
|
+
"use strict";
|
|
33071
|
+
init_esm_shims();
|
|
33072
|
+
STOP_WORDS = /* @__PURE__ */ new Set([
|
|
33073
|
+
"a",
|
|
33074
|
+
"an",
|
|
33075
|
+
"and",
|
|
33076
|
+
"as",
|
|
33077
|
+
"for",
|
|
33078
|
+
"in",
|
|
33079
|
+
"into",
|
|
33080
|
+
"of",
|
|
33081
|
+
"on",
|
|
33082
|
+
"onto",
|
|
33083
|
+
"the",
|
|
33084
|
+
"this",
|
|
33085
|
+
"that",
|
|
33086
|
+
"to",
|
|
33087
|
+
"with",
|
|
33088
|
+
"work",
|
|
33089
|
+
"project",
|
|
33090
|
+
"continue",
|
|
33091
|
+
"\u7EE7\u7EED",
|
|
33092
|
+
"\u9879\u76EE"
|
|
33093
|
+
]);
|
|
33094
|
+
LENSES = {
|
|
33095
|
+
bugfix: {
|
|
33096
|
+
id: "bugfix",
|
|
33097
|
+
description: "debug the failure with current code and the smallest repro first",
|
|
33098
|
+
sourceLimit: 6,
|
|
33099
|
+
cautionLimit: 4,
|
|
33100
|
+
hideUnrelatedCautionDetails: true,
|
|
33101
|
+
hideUnrelatedReliableDetails: false
|
|
33102
|
+
},
|
|
33103
|
+
feature: {
|
|
33104
|
+
id: "feature",
|
|
33105
|
+
description: "build a scoped feature from nearby source, types, and user flow",
|
|
33106
|
+
sourceLimit: 6,
|
|
33107
|
+
cautionLimit: 3,
|
|
33108
|
+
hideUnrelatedCautionDetails: true,
|
|
33109
|
+
hideUnrelatedReliableDetails: false
|
|
33110
|
+
},
|
|
33111
|
+
release: {
|
|
33112
|
+
id: "release",
|
|
33113
|
+
description: "prepare a release using current metadata, changelog, build, and package checks",
|
|
33114
|
+
sourceLimit: 4,
|
|
33115
|
+
cautionLimit: 2,
|
|
33116
|
+
hideUnrelatedCautionDetails: true,
|
|
33117
|
+
hideUnrelatedReliableDetails: true
|
|
33118
|
+
},
|
|
33119
|
+
onboarding: {
|
|
33120
|
+
id: "onboarding",
|
|
33121
|
+
description: "understand the project shape before trusting old implementation details",
|
|
33122
|
+
sourceLimit: 4,
|
|
33123
|
+
cautionLimit: 2,
|
|
33124
|
+
hideUnrelatedCautionDetails: true,
|
|
33125
|
+
hideUnrelatedReliableDetails: true
|
|
33126
|
+
},
|
|
33127
|
+
refactor: {
|
|
33128
|
+
id: "refactor",
|
|
33129
|
+
description: "change structure carefully by reading shared code, call sites, and tests",
|
|
33130
|
+
sourceLimit: 6,
|
|
33131
|
+
cautionLimit: 4,
|
|
33132
|
+
hideUnrelatedCautionDetails: true,
|
|
33133
|
+
hideUnrelatedReliableDetails: false
|
|
33134
|
+
},
|
|
33135
|
+
docs: {
|
|
33136
|
+
id: "docs",
|
|
33137
|
+
description: "update documentation against current code and public entry points",
|
|
33138
|
+
sourceLimit: 5,
|
|
33139
|
+
cautionLimit: 2,
|
|
33140
|
+
hideUnrelatedCautionDetails: true,
|
|
33141
|
+
hideUnrelatedReliableDetails: true
|
|
33142
|
+
},
|
|
33143
|
+
test: {
|
|
33144
|
+
id: "test",
|
|
33145
|
+
description: "work from tests, fixtures, harnesses, and the related source files",
|
|
33146
|
+
sourceLimit: 6,
|
|
33147
|
+
cautionLimit: 3,
|
|
33148
|
+
hideUnrelatedCautionDetails: true,
|
|
33149
|
+
hideUnrelatedReliableDetails: false
|
|
33150
|
+
},
|
|
33151
|
+
general: {
|
|
33152
|
+
id: "general",
|
|
33153
|
+
description: "balanced project handoff with current facts, code memory, and verification hints",
|
|
33154
|
+
sourceLimit: 8,
|
|
33155
|
+
cautionLimit: 5,
|
|
33156
|
+
hideUnrelatedCautionDetails: false,
|
|
33157
|
+
hideUnrelatedReliableDetails: false
|
|
33158
|
+
}
|
|
33159
|
+
};
|
|
33160
|
+
KEYWORDS = {
|
|
33161
|
+
bugfix: [
|
|
33162
|
+
"bug",
|
|
33163
|
+
"crash",
|
|
33164
|
+
"incident",
|
|
33165
|
+
"debug",
|
|
33166
|
+
"error",
|
|
33167
|
+
"fail",
|
|
33168
|
+
"failing",
|
|
33169
|
+
"fix",
|
|
33170
|
+
"issue",
|
|
33171
|
+
"regression",
|
|
33172
|
+
"repro",
|
|
33173
|
+
"\u62A5\u9519",
|
|
33174
|
+
"\u5D29\u6E83",
|
|
33175
|
+
"\u6545\u969C",
|
|
33176
|
+
"\u5931\u8D25",
|
|
33177
|
+
"\u4FEE\u590D",
|
|
33178
|
+
"\u95EE\u9898"
|
|
33179
|
+
],
|
|
33180
|
+
feature: ["add", "build", "feature", "implement", "new", "support", "\u65B0\u589E", "\u5B9E\u73B0", "\u652F\u6301", "\u529F\u80FD"],
|
|
33181
|
+
release: ["bump", "changelog", "npm", "pack", "publish", "release", "version", "\u53D1\u7248", "\u53D1\u5E03", "\u7248\u672C"],
|
|
33182
|
+
onboarding: ["architecture", "handoff", "onboard", "overview", "understand", "\u63A5\u624B", "\u4E86\u89E3", "\u7406\u89E3", "\u67B6\u6784"],
|
|
33183
|
+
refactor: ["cleanup", "migrate", "refactor", "rename", "restructure", "\u91CD\u6784", "\u8FC1\u79FB", "\u6539\u9020"],
|
|
33184
|
+
docs: ["doc", "docs", "readme", "\u6587\u6863", "\u8BF4\u660E"],
|
|
33185
|
+
test: ["coverage", "fixture", "smoke", "spec", "test", "tests", "testing", "vitest", "\u6D4B\u8BD5"]
|
|
33186
|
+
};
|
|
33187
|
+
LENS_PRIORITY = [
|
|
33188
|
+
"bugfix",
|
|
33189
|
+
"release",
|
|
33190
|
+
"test",
|
|
33191
|
+
"refactor",
|
|
33192
|
+
"feature",
|
|
33193
|
+
"docs",
|
|
33194
|
+
"onboarding"
|
|
33195
|
+
];
|
|
33196
|
+
}
|
|
33197
|
+
});
|
|
33198
|
+
|
|
32814
33199
|
// src/knowledge/workflows.ts
|
|
32815
33200
|
var workflows_exports = {};
|
|
32816
33201
|
__export(workflows_exports, {
|
|
@@ -33132,20 +33517,27 @@ function taskScore(workflow, task) {
|
|
|
33132
33517
|
const text = task.toLowerCase();
|
|
33133
33518
|
let score = 0;
|
|
33134
33519
|
const reasons = [];
|
|
33520
|
+
const matchedLenses = /* @__PURE__ */ new Set();
|
|
33521
|
+
const matchedTriggers = /* @__PURE__ */ new Set();
|
|
33135
33522
|
for (const lens of workflow.taskLenses) {
|
|
33136
33523
|
const terms = LENS_TERMS[lens.toLowerCase()] ?? [lens.toLowerCase()];
|
|
33137
|
-
if (terms.some((term) =>
|
|
33524
|
+
if (terms.some((term) => containsTaskKeyword(task, term))) {
|
|
33138
33525
|
score += 20;
|
|
33139
33526
|
reasons.push("matches " + lens + " workflow");
|
|
33527
|
+
matchedLenses.add(lens.toLowerCase());
|
|
33140
33528
|
}
|
|
33141
33529
|
}
|
|
33142
33530
|
for (const trigger of workflow.triggers) {
|
|
33143
33531
|
const term = trigger.toLowerCase().trim();
|
|
33144
|
-
if (term.length >= 2 &&
|
|
33532
|
+
if (term.length >= 2 && containsTaskKeyword(task, term)) {
|
|
33145
33533
|
score += 8;
|
|
33146
33534
|
reasons.push('matches trigger "' + trigger + '"');
|
|
33535
|
+
matchedTriggers.add(term);
|
|
33147
33536
|
}
|
|
33148
33537
|
}
|
|
33538
|
+
const hasSpecificLens = workflow.taskLenses.some((lens) => !GENERIC_WORKFLOW_LENSES.has(lens.toLowerCase()));
|
|
33539
|
+
const hasSpecificMatch = [...matchedLenses].some((lens) => !GENERIC_WORKFLOW_LENSES.has(lens)) || [...matchedTriggers].some((trigger) => !GENERIC_WORKFLOW_TERMS.has(trigger));
|
|
33540
|
+
if (hasSpecificLens && !hasSpecificMatch) return { score: 0, reasons: [] };
|
|
33149
33541
|
return { score, reasons: [...new Set(reasons)] };
|
|
33150
33542
|
}
|
|
33151
33543
|
function selectWorkflows(input) {
|
|
@@ -33163,9 +33555,28 @@ function selectWorkflows(input) {
|
|
|
33163
33555
|
return selected.slice(0, Math.max(1, Math.min(input.limit ?? 2, 2)));
|
|
33164
33556
|
}
|
|
33165
33557
|
function importedWorkflowSpec(input) {
|
|
33558
|
+
let sourceMatter;
|
|
33559
|
+
try {
|
|
33560
|
+
sourceMatter = (0, import_gray_matter2.default)(input.raw);
|
|
33561
|
+
} catch (error2) {
|
|
33562
|
+
throw new Error("Malformed Windsurf workflow Markdown: " + (error2 instanceof Error ? error2.message : String(error2)));
|
|
33563
|
+
}
|
|
33564
|
+
if (sourceMatter.data.id !== void 0) {
|
|
33565
|
+
const id = requiredText(sourceMatter.data, "id");
|
|
33566
|
+
const sourcePath2 = "workflows/" + slug(id) + ".md";
|
|
33567
|
+
const canonical = parsedWorkflow(sourceMatter.data, sourceMatter.content, {
|
|
33568
|
+
workspaceId: input.workspace.id,
|
|
33569
|
+
sourcePath: sourcePath2,
|
|
33570
|
+
contentHash: hash2(input.raw)
|
|
33571
|
+
});
|
|
33572
|
+
return materializeWorkflow({
|
|
33573
|
+
...canonical,
|
|
33574
|
+
importedFrom: input.sourcePath.replace(/\\/g, "/")
|
|
33575
|
+
});
|
|
33576
|
+
}
|
|
33166
33577
|
const entry = new WorkflowSyncer().parseWindsurfWorkflow(input.sourceName, input.raw);
|
|
33167
33578
|
const content = entry.content.trim() || "## Execute\n\nFollow the imported workflow.";
|
|
33168
|
-
const lenses = inferTaskLenses(entry.name + "\n" + entry.description
|
|
33579
|
+
const lenses = inferTaskLenses(entry.name + "\n" + entry.description);
|
|
33169
33580
|
const createdAt = now();
|
|
33170
33581
|
const sourcePath = "workflows/" + slug(entry.name) + ".md";
|
|
33171
33582
|
const spec = {
|
|
@@ -33386,7 +33797,7 @@ async function selectWorkspaceWorkflows(input) {
|
|
|
33386
33797
|
errors: synced.errors
|
|
33387
33798
|
};
|
|
33388
33799
|
}
|
|
33389
|
-
var import_gray_matter2, KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS;
|
|
33800
|
+
var import_gray_matter2, KNOWN_AGENTS, WORKFLOW_ADAPTER_TARGETS, STATUS_VALUES, LENS_TERMS, GENERIC_WORKFLOW_LENSES, GENERIC_WORKFLOW_TERMS;
|
|
33390
33801
|
var init_workflows = __esm({
|
|
33391
33802
|
"src/knowledge/workflows.ts"() {
|
|
33392
33803
|
"use strict";
|
|
@@ -33396,6 +33807,7 @@ var init_workflows = __esm({
|
|
|
33396
33807
|
init_workflow_sync();
|
|
33397
33808
|
init_workspace();
|
|
33398
33809
|
init_workflow_store();
|
|
33810
|
+
init_task_lens();
|
|
33399
33811
|
KNOWN_AGENTS = [
|
|
33400
33812
|
"windsurf",
|
|
33401
33813
|
"cursor",
|
|
@@ -33427,6 +33839,8 @@ var init_workflows = __esm({
|
|
|
33427
33839
|
refactor: ["refactor", "cleanup", "restructure", "\u91CD\u6784", "\u6574\u7406"],
|
|
33428
33840
|
test: ["test", "verify", "smoke", "\u6D4B\u8BD5", "\u9A8C\u8BC1"]
|
|
33429
33841
|
};
|
|
33842
|
+
GENERIC_WORKFLOW_LENSES = /* @__PURE__ */ new Set(["review", "test"]);
|
|
33843
|
+
GENERIC_WORKFLOW_TERMS = /* @__PURE__ */ new Set(["review", "audit", "test", "verify", "smoke"]);
|
|
33430
33844
|
}
|
|
33431
33845
|
});
|
|
33432
33846
|
|
|
@@ -33774,7 +34188,8 @@ var init_workset = __esm({
|
|
|
33774
34188
|
// src/codegraph/current-facts.ts
|
|
33775
34189
|
var current_facts_exports = {};
|
|
33776
34190
|
__export(current_facts_exports, {
|
|
33777
|
-
collectCurrentProjectFacts: () => collectCurrentProjectFacts
|
|
34191
|
+
collectCurrentProjectFacts: () => collectCurrentProjectFacts,
|
|
34192
|
+
formatGitFact: () => formatGitFact
|
|
33778
34193
|
});
|
|
33779
34194
|
import { execFileSync } from "child_process";
|
|
33780
34195
|
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
@@ -33819,11 +34234,16 @@ function runGit(rootPath, args) {
|
|
|
33819
34234
|
}
|
|
33820
34235
|
}
|
|
33821
34236
|
function readGitFacts(rootPath) {
|
|
33822
|
-
const
|
|
34237
|
+
const available = runGit(rootPath, ["rev-parse", "--is-inside-work-tree"]) === "true";
|
|
34238
|
+
if (!available) {
|
|
34239
|
+
return { available: false, dirty: false, detached: false };
|
|
34240
|
+
}
|
|
34241
|
+
const branch = runGit(rootPath, ["symbolic-ref", "--quiet", "--short", "HEAD"]) ?? runGit(rootPath, ["branch", "--show-current"]);
|
|
33823
34242
|
const commit = runGit(rootPath, ["rev-parse", "--short", "HEAD"]);
|
|
33824
34243
|
const latestCommit = runGit(rootPath, ["log", "-1", "--pretty=%s"]);
|
|
33825
34244
|
const dirty = Boolean(runGit(rootPath, ["status", "--porcelain"]));
|
|
33826
34245
|
return {
|
|
34246
|
+
available: true,
|
|
33827
34247
|
...branch ? { branch } : {},
|
|
33828
34248
|
...commit ? { commit } : {},
|
|
33829
34249
|
...latestCommit ? { latestCommit } : {},
|
|
@@ -33831,6 +34251,15 @@ function readGitFacts(rootPath) {
|
|
|
33831
34251
|
detached: !branch
|
|
33832
34252
|
};
|
|
33833
34253
|
}
|
|
34254
|
+
function formatGitFact(git) {
|
|
34255
|
+
if (!git.available) return "Git: unavailable";
|
|
34256
|
+
const parts = [];
|
|
34257
|
+
if (git.detached) parts.push("detached HEAD");
|
|
34258
|
+
else if (git.branch) parts.push("branch " + git.branch);
|
|
34259
|
+
if (git.commit) parts.push("commit " + git.commit);
|
|
34260
|
+
parts.push(git.dirty ? "dirty worktree" : "clean worktree");
|
|
34261
|
+
return "Git: " + parts.join(", ");
|
|
34262
|
+
}
|
|
33834
34263
|
function parseProgressNote(content) {
|
|
33835
34264
|
const lastUpdated = content.match(/Last updated\*\*:\s*(\d{4}-\d{2}-\d{2})/i) ?? content.match(/Last updated:\s*(\d{4}-\d{2}-\d{2})/i);
|
|
33836
34265
|
const branchHint = content.match(/Branch\*\*:\s*([^\r\n]+)/i) ?? content.match(/Branch:\s*([^\r\n]+)/i);
|
|
@@ -35101,319 +35530,6 @@ var init_project_context = __esm({
|
|
|
35101
35530
|
}
|
|
35102
35531
|
});
|
|
35103
35532
|
|
|
35104
|
-
// src/codegraph/task-lens.ts
|
|
35105
|
-
var task_lens_exports = {};
|
|
35106
|
-
__export(task_lens_exports, {
|
|
35107
|
-
lensPathCandidates: () => lensPathCandidates,
|
|
35108
|
-
lensVerificationHints: () => lensVerificationHints,
|
|
35109
|
-
rankLensPaths: () => rankLensPaths,
|
|
35110
|
-
rankLensSources: () => rankLensSources,
|
|
35111
|
-
resolveTaskLens: () => resolveTaskLens,
|
|
35112
|
-
scoreLensSource: () => scoreLensSource,
|
|
35113
|
-
shouldShowLensSource: () => shouldShowLensSource
|
|
35114
|
-
});
|
|
35115
|
-
function normalizePath2(path34) {
|
|
35116
|
-
return path34.replace(/\\/g, "/");
|
|
35117
|
-
}
|
|
35118
|
-
function tokenize3(text) {
|
|
35119
|
-
return (text.toLowerCase().match(/[a-z0-9_./-]+|[\u4e00-\u9fff]+/g) ?? []).map((token) => token.trim()).filter((token) => token.length > 1 && !STOP_WORDS.has(token));
|
|
35120
|
-
}
|
|
35121
|
-
function containsKeyword(text, keyword) {
|
|
35122
|
-
if (/^[a-z0-9_-]+$/i.test(keyword)) {
|
|
35123
|
-
return new RegExp(`(^|[^a-z0-9_-])${keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([^a-z0-9_-]|$)`, "i").test(text);
|
|
35124
|
-
}
|
|
35125
|
-
return text.includes(keyword);
|
|
35126
|
-
}
|
|
35127
|
-
function resolveTaskLens(task) {
|
|
35128
|
-
const normalized = (task ?? "").toLowerCase();
|
|
35129
|
-
if (!normalized.trim()) return LENSES.general;
|
|
35130
|
-
let best = {
|
|
35131
|
-
id: "general",
|
|
35132
|
-
score: 0,
|
|
35133
|
-
priority: Number.MAX_SAFE_INTEGER
|
|
35134
|
-
};
|
|
35135
|
-
for (const id of LENS_PRIORITY) {
|
|
35136
|
-
const score = KEYWORDS[id].reduce((sum, keyword) => sum + (containsKeyword(normalized, keyword) ? 1 : 0), 0);
|
|
35137
|
-
const priority = LENS_PRIORITY.indexOf(id);
|
|
35138
|
-
if (score > best.score || score === best.score && score > 0 && priority < best.priority) {
|
|
35139
|
-
best = { id, score, priority };
|
|
35140
|
-
}
|
|
35141
|
-
}
|
|
35142
|
-
return best.score > 0 ? LENSES[best.id] : LENSES.general;
|
|
35143
|
-
}
|
|
35144
|
-
function pathKindScore(path34, lens) {
|
|
35145
|
-
const normalized = normalizePath2(path34).toLowerCase();
|
|
35146
|
-
const name = normalized.split("/").pop() ?? normalized;
|
|
35147
|
-
const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
|
|
35148
|
-
const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
|
|
35149
|
-
const isSource = normalized.startsWith("src/") || normalized.includes("/src/");
|
|
35150
|
-
const isPackage = name === "package.json" || name === "package-lock.json" || name === "pnpm-lock.yaml" || name === "yarn.lock";
|
|
35151
|
-
const isChangelog = name === "changelog.md" || name === "changes.md";
|
|
35152
|
-
const isWorkflow = normalized.startsWith(".github/workflows/");
|
|
35153
|
-
switch (lens.id) {
|
|
35154
|
-
case "bugfix":
|
|
35155
|
-
return (isTest ? 80 : 0) + (isSource ? 50 : 0) + (normalized.includes("debug") ? 20 : 0);
|
|
35156
|
-
case "test":
|
|
35157
|
-
return (isTest ? 90 : 0) + (isSource ? 45 : 0);
|
|
35158
|
-
case "release":
|
|
35159
|
-
return (isChangelog ? 100 : 0) + (isPackage ? 90 : 0) + (isWorkflow ? 70 : 0) + (inDocs ? 35 : 0);
|
|
35160
|
-
case "onboarding":
|
|
35161
|
-
return (name === "readme.md" ? 100 : 0) + (inDocs ? 80 : 0) + (isPackage ? 45 : 0) + (isSource ? 20 : 0);
|
|
35162
|
-
case "docs":
|
|
35163
|
-
return (inDocs ? 100 : 0) + (isChangelog ? 60 : 0) + (isSource ? 25 : 0);
|
|
35164
|
-
case "refactor":
|
|
35165
|
-
return (isSource ? 70 : 0) + (isTest ? 65 : 0);
|
|
35166
|
-
case "feature":
|
|
35167
|
-
return (isSource ? 80 : 0) + (isTest ? 45 : 0) + (inDocs ? 20 : 0);
|
|
35168
|
-
default:
|
|
35169
|
-
if (isSource || isTest) return 60;
|
|
35170
|
-
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 45;
|
|
35171
|
-
if (inDocs) return 20;
|
|
35172
|
-
return 0;
|
|
35173
|
-
}
|
|
35174
|
-
}
|
|
35175
|
-
function tokenScore(text, tokens) {
|
|
35176
|
-
if (tokens.length === 0) return 0;
|
|
35177
|
-
const normalized = text.toLowerCase();
|
|
35178
|
-
return tokens.reduce((sum, token) => sum + (normalized.includes(token) ? 12 : 0), 0);
|
|
35179
|
-
}
|
|
35180
|
-
function sourceTaskMatchScore(source, task) {
|
|
35181
|
-
const tokens = tokenize3(task ?? "");
|
|
35182
|
-
if (tokens.length === 0) return 0;
|
|
35183
|
-
const text = [
|
|
35184
|
-
source.title,
|
|
35185
|
-
source.path ?? "",
|
|
35186
|
-
source.symbol ?? ""
|
|
35187
|
-
].join("\n").toLowerCase();
|
|
35188
|
-
const matches = tokens.filter((token) => text.includes(token)).length;
|
|
35189
|
-
if (matches >= 2) return 40;
|
|
35190
|
-
if (matches === 1) return 24;
|
|
35191
|
-
return 0;
|
|
35192
|
-
}
|
|
35193
|
-
function fallbackPathRank(path34) {
|
|
35194
|
-
const normalized = normalizePath2(path34);
|
|
35195
|
-
if (normalized.startsWith("src/")) return 0;
|
|
35196
|
-
if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
|
|
35197
|
-
if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
|
|
35198
|
-
if (normalized.startsWith("docs/") || normalized.toLowerCase() === "readme.md") return 3;
|
|
35199
|
-
return 4;
|
|
35200
|
-
}
|
|
35201
|
-
function rankLensPaths(paths, lens, task) {
|
|
35202
|
-
const tokens = tokenize3(task ?? "");
|
|
35203
|
-
return [...new Set(paths.map(normalizePath2))].map((path34, index) => ({
|
|
35204
|
-
path: path34,
|
|
35205
|
-
index,
|
|
35206
|
-
score: pathKindScore(path34, lens) + tokenScore(path34, tokens),
|
|
35207
|
-
fallback: fallbackPathRank(path34)
|
|
35208
|
-
})).sort((a3, b3) => b3.score - a3.score || a3.fallback - b3.fallback || a3.index - b3.index || a3.path.localeCompare(b3.path)).map((item) => item.path);
|
|
35209
|
-
}
|
|
35210
|
-
function lensPathCandidates(lens) {
|
|
35211
|
-
switch (lens.id) {
|
|
35212
|
-
case "release":
|
|
35213
|
-
return ["CHANGELOG.md", "package.json", "package-lock.json", ".github/workflows/ci.yml", ".github/workflows/test.yml", "README.md"];
|
|
35214
|
-
case "onboarding":
|
|
35215
|
-
return ["README.md", "docs/README.md", "docs/API_REFERENCE.md", "package.json"];
|
|
35216
|
-
case "docs":
|
|
35217
|
-
return ["README.md", "README.zh-CN.md", "docs/README.md", "docs/API_REFERENCE.md", "CHANGELOG.md"];
|
|
35218
|
-
case "test":
|
|
35219
|
-
case "bugfix":
|
|
35220
|
-
return ["tests", "test"];
|
|
35221
|
-
default:
|
|
35222
|
-
return [];
|
|
35223
|
-
}
|
|
35224
|
-
}
|
|
35225
|
-
function scoreLensSource(source, lens, task) {
|
|
35226
|
-
const tokens = tokenize3(task ?? "");
|
|
35227
|
-
const text = [source.title, source.type, source.path ?? "", source.symbol ?? ""].join("\n");
|
|
35228
|
-
return pathKindScore(source.path ?? "", lens) + tokenScore(text, tokens) + sourceTaskMatchScore(source, task);
|
|
35229
|
-
}
|
|
35230
|
-
function rankLensSources(sources, lens, task) {
|
|
35231
|
-
return [...sources].map((source, index) => ({
|
|
35232
|
-
source,
|
|
35233
|
-
index,
|
|
35234
|
-
score: scoreLensSource(source, lens, task)
|
|
35235
|
-
})).sort((a3, b3) => b3.score - a3.score || a3.source.observationId - b3.source.observationId || a3.index - b3.index).map((item) => item.source);
|
|
35236
|
-
}
|
|
35237
|
-
function lensVerificationHints(lens) {
|
|
35238
|
-
switch (lens.id) {
|
|
35239
|
-
case "bugfix":
|
|
35240
|
-
return [
|
|
35241
|
-
"run the smallest failing test or repro first",
|
|
35242
|
-
"inspect the changed code path before trusting old memory"
|
|
35243
|
-
];
|
|
35244
|
-
case "test":
|
|
35245
|
-
return [
|
|
35246
|
-
"run the exact focused test file or test name first",
|
|
35247
|
-
"inspect fixtures and harness setup before changing assertions"
|
|
35248
|
-
];
|
|
35249
|
-
case "release":
|
|
35250
|
-
return [
|
|
35251
|
-
"run build, tests, package smoke, and publish dry-run where available",
|
|
35252
|
-
"verify package metadata, changelog, and Git state before publishing"
|
|
35253
|
-
];
|
|
35254
|
-
case "onboarding":
|
|
35255
|
-
return [
|
|
35256
|
-
"read the docs/start files first, then inspect only the code paths needed for the task",
|
|
35257
|
-
"treat old implementation memories as leads until current code confirms them"
|
|
35258
|
-
];
|
|
35259
|
-
case "refactor":
|
|
35260
|
-
return [
|
|
35261
|
-
"inspect call sites and tests before editing shared code",
|
|
35262
|
-
"run the narrow affected test plus one regression smoke"
|
|
35263
|
-
];
|
|
35264
|
-
case "docs":
|
|
35265
|
-
return [
|
|
35266
|
-
"check headings, links, commands, and examples against current code",
|
|
35267
|
-
"run the smallest docs or package smoke available"
|
|
35268
|
-
];
|
|
35269
|
-
case "feature":
|
|
35270
|
-
return [
|
|
35271
|
-
"inspect the closest existing implementation pattern before adding new code",
|
|
35272
|
-
"run focused tests plus one user-flow smoke after changes"
|
|
35273
|
-
];
|
|
35274
|
-
default:
|
|
35275
|
-
return [
|
|
35276
|
-
"inspect the Start here files before editing",
|
|
35277
|
-
"run the smallest relevant test or smoke command after changes"
|
|
35278
|
-
];
|
|
35279
|
-
}
|
|
35280
|
-
}
|
|
35281
|
-
function shouldShowLensSource(source, lens, task) {
|
|
35282
|
-
if (lens.id === "general") return true;
|
|
35283
|
-
const score = scoreLensSource(source, lens, task);
|
|
35284
|
-
if (lens.id === "onboarding" || lens.id === "release" || lens.id === "docs") return score >= 40;
|
|
35285
|
-
return score > 0;
|
|
35286
|
-
}
|
|
35287
|
-
var STOP_WORDS, LENSES, KEYWORDS, LENS_PRIORITY;
|
|
35288
|
-
var init_task_lens = __esm({
|
|
35289
|
-
"src/codegraph/task-lens.ts"() {
|
|
35290
|
-
"use strict";
|
|
35291
|
-
init_esm_shims();
|
|
35292
|
-
STOP_WORDS = /* @__PURE__ */ new Set([
|
|
35293
|
-
"a",
|
|
35294
|
-
"an",
|
|
35295
|
-
"and",
|
|
35296
|
-
"as",
|
|
35297
|
-
"for",
|
|
35298
|
-
"in",
|
|
35299
|
-
"into",
|
|
35300
|
-
"of",
|
|
35301
|
-
"on",
|
|
35302
|
-
"onto",
|
|
35303
|
-
"the",
|
|
35304
|
-
"this",
|
|
35305
|
-
"that",
|
|
35306
|
-
"to",
|
|
35307
|
-
"with",
|
|
35308
|
-
"work",
|
|
35309
|
-
"project",
|
|
35310
|
-
"continue",
|
|
35311
|
-
"\u7EE7\u7EED",
|
|
35312
|
-
"\u9879\u76EE"
|
|
35313
|
-
]);
|
|
35314
|
-
LENSES = {
|
|
35315
|
-
bugfix: {
|
|
35316
|
-
id: "bugfix",
|
|
35317
|
-
description: "debug the failure with current code and the smallest repro first",
|
|
35318
|
-
sourceLimit: 6,
|
|
35319
|
-
cautionLimit: 4,
|
|
35320
|
-
hideUnrelatedCautionDetails: true,
|
|
35321
|
-
hideUnrelatedReliableDetails: false
|
|
35322
|
-
},
|
|
35323
|
-
feature: {
|
|
35324
|
-
id: "feature",
|
|
35325
|
-
description: "build a scoped feature from nearby source, types, and user flow",
|
|
35326
|
-
sourceLimit: 6,
|
|
35327
|
-
cautionLimit: 3,
|
|
35328
|
-
hideUnrelatedCautionDetails: true,
|
|
35329
|
-
hideUnrelatedReliableDetails: false
|
|
35330
|
-
},
|
|
35331
|
-
release: {
|
|
35332
|
-
id: "release",
|
|
35333
|
-
description: "prepare a release using current metadata, changelog, build, and package checks",
|
|
35334
|
-
sourceLimit: 4,
|
|
35335
|
-
cautionLimit: 2,
|
|
35336
|
-
hideUnrelatedCautionDetails: true,
|
|
35337
|
-
hideUnrelatedReliableDetails: true
|
|
35338
|
-
},
|
|
35339
|
-
onboarding: {
|
|
35340
|
-
id: "onboarding",
|
|
35341
|
-
description: "understand the project shape before trusting old implementation details",
|
|
35342
|
-
sourceLimit: 4,
|
|
35343
|
-
cautionLimit: 2,
|
|
35344
|
-
hideUnrelatedCautionDetails: true,
|
|
35345
|
-
hideUnrelatedReliableDetails: true
|
|
35346
|
-
},
|
|
35347
|
-
refactor: {
|
|
35348
|
-
id: "refactor",
|
|
35349
|
-
description: "change structure carefully by reading shared code, call sites, and tests",
|
|
35350
|
-
sourceLimit: 6,
|
|
35351
|
-
cautionLimit: 4,
|
|
35352
|
-
hideUnrelatedCautionDetails: true,
|
|
35353
|
-
hideUnrelatedReliableDetails: false
|
|
35354
|
-
},
|
|
35355
|
-
docs: {
|
|
35356
|
-
id: "docs",
|
|
35357
|
-
description: "update documentation against current code and public entry points",
|
|
35358
|
-
sourceLimit: 5,
|
|
35359
|
-
cautionLimit: 2,
|
|
35360
|
-
hideUnrelatedCautionDetails: true,
|
|
35361
|
-
hideUnrelatedReliableDetails: true
|
|
35362
|
-
},
|
|
35363
|
-
test: {
|
|
35364
|
-
id: "test",
|
|
35365
|
-
description: "work from tests, fixtures, harnesses, and the related source files",
|
|
35366
|
-
sourceLimit: 6,
|
|
35367
|
-
cautionLimit: 3,
|
|
35368
|
-
hideUnrelatedCautionDetails: true,
|
|
35369
|
-
hideUnrelatedReliableDetails: false
|
|
35370
|
-
},
|
|
35371
|
-
general: {
|
|
35372
|
-
id: "general",
|
|
35373
|
-
description: "balanced project handoff with current facts, code memory, and verification hints",
|
|
35374
|
-
sourceLimit: 8,
|
|
35375
|
-
cautionLimit: 5,
|
|
35376
|
-
hideUnrelatedCautionDetails: false,
|
|
35377
|
-
hideUnrelatedReliableDetails: false
|
|
35378
|
-
}
|
|
35379
|
-
};
|
|
35380
|
-
KEYWORDS = {
|
|
35381
|
-
bugfix: [
|
|
35382
|
-
"bug",
|
|
35383
|
-
"crash",
|
|
35384
|
-
"debug",
|
|
35385
|
-
"error",
|
|
35386
|
-
"fail",
|
|
35387
|
-
"failing",
|
|
35388
|
-
"fix",
|
|
35389
|
-
"issue",
|
|
35390
|
-
"regression",
|
|
35391
|
-
"repro",
|
|
35392
|
-
"\u62A5\u9519",
|
|
35393
|
-
"\u5D29\u6E83",
|
|
35394
|
-
"\u5931\u8D25",
|
|
35395
|
-
"\u4FEE\u590D",
|
|
35396
|
-
"\u95EE\u9898"
|
|
35397
|
-
],
|
|
35398
|
-
feature: ["add", "build", "feature", "implement", "new", "support", "\u65B0\u589E", "\u5B9E\u73B0", "\u652F\u6301", "\u529F\u80FD"],
|
|
35399
|
-
release: ["bump", "changelog", "npm", "pack", "publish", "release", "version", "\u53D1\u7248", "\u53D1\u5E03", "\u7248\u672C"],
|
|
35400
|
-
onboarding: ["architecture", "handoff", "onboard", "overview", "understand", "\u63A5\u624B", "\u4E86\u89E3", "\u7406\u89E3", "\u67B6\u6784"],
|
|
35401
|
-
refactor: ["cleanup", "migrate", "refactor", "rename", "restructure", "\u91CD\u6784", "\u8FC1\u79FB", "\u6539\u9020"],
|
|
35402
|
-
docs: ["doc", "docs", "readme", "\u6587\u6863", "\u8BF4\u660E"],
|
|
35403
|
-
test: ["coverage", "fixture", "smoke", "spec", "test", "tests", "testing", "vitest", "\u6D4B\u8BD5"]
|
|
35404
|
-
};
|
|
35405
|
-
LENS_PRIORITY = [
|
|
35406
|
-
"bugfix",
|
|
35407
|
-
"release",
|
|
35408
|
-
"test",
|
|
35409
|
-
"refactor",
|
|
35410
|
-
"feature",
|
|
35411
|
-
"docs",
|
|
35412
|
-
"onboarding"
|
|
35413
|
-
];
|
|
35414
|
-
}
|
|
35415
|
-
});
|
|
35416
|
-
|
|
35417
35533
|
// src/codegraph/auto-context.ts
|
|
35418
35534
|
var auto_context_exports = {};
|
|
35419
35535
|
__export(auto_context_exports, {
|
|
@@ -35709,15 +35825,7 @@ function formatCurrentFactsLines(facts) {
|
|
|
35709
35825
|
if (facts.latestChangelog) {
|
|
35710
35826
|
lines.push(`- Latest changelog: ${facts.latestChangelog.version}${facts.latestChangelog.date ? ` (${facts.latestChangelog.date})` : ""}`);
|
|
35711
35827
|
}
|
|
35712
|
-
|
|
35713
|
-
if (facts.git.detached) {
|
|
35714
|
-
gitParts.push("detached HEAD");
|
|
35715
|
-
} else if (facts.git.branch) {
|
|
35716
|
-
gitParts.push(`branch ${facts.git.branch}`);
|
|
35717
|
-
}
|
|
35718
|
-
if (facts.git.commit) gitParts.push(`commit ${facts.git.commit}`);
|
|
35719
|
-
gitParts.push(facts.git.dirty ? "dirty worktree" : "clean worktree");
|
|
35720
|
-
lines.push(`- Git: ${gitParts.join(", ")}`);
|
|
35828
|
+
lines.push("- " + formatGitFact(facts.git));
|
|
35721
35829
|
if (facts.git.latestCommit) lines.push(`- Latest commit: ${facts.git.latestCommit}`);
|
|
35722
35830
|
lines.push("- Current facts above outrank progress/dev-log files when they conflict.");
|
|
35723
35831
|
if (facts.staleNotes.length > 0) {
|
|
@@ -35739,11 +35847,7 @@ function worksetFactLines(facts) {
|
|
|
35739
35847
|
if (facts.latestChangelog) {
|
|
35740
35848
|
lines.push("Latest changelog: " + facts.latestChangelog.version + (facts.latestChangelog.date ? " (" + facts.latestChangelog.date + ")" : ""));
|
|
35741
35849
|
}
|
|
35742
|
-
|
|
35743
|
-
if (facts.git.branch) gitParts.push("branch " + facts.git.branch);
|
|
35744
|
-
if (facts.git.commit) gitParts.push("commit " + facts.git.commit);
|
|
35745
|
-
gitParts.push(facts.git.dirty ? "dirty worktree" : "clean worktree");
|
|
35746
|
-
lines.push("Git: " + gitParts.join(", "));
|
|
35850
|
+
lines.push(formatGitFact(facts.git));
|
|
35747
35851
|
for (const note of facts.staleNotes.slice(0, 1)) {
|
|
35748
35852
|
lines.push(
|
|
35749
35853
|
"Historical note: " + note.path + (note.branchHint ? " (branch hint " + note.branchHint + "; " + note.reason + ")" : " (" + note.reason + ")")
|
|
@@ -36263,7 +36367,7 @@ function compactFacts(project) {
|
|
|
36263
36367
|
if (current.latestChangelog) {
|
|
36264
36368
|
facts.push("Latest changelog: " + current.latestChangelog.version + (current.latestChangelog.date ? " (" + current.latestChangelog.date + ")" : ""));
|
|
36265
36369
|
}
|
|
36266
|
-
facts.push(
|
|
36370
|
+
facts.push(formatGitFact(current.git));
|
|
36267
36371
|
return { facts, dirty: current.git.dirty };
|
|
36268
36372
|
}
|
|
36269
36373
|
var codegraph_default;
|
|
@@ -36999,6 +37103,8 @@ function usage() {
|
|
|
36999
37103
|
" memorix knowledge init [--mode local]",
|
|
37000
37104
|
" memorix knowledge init --mode versioned --path C:\\project\\docs\\knowledge",
|
|
37001
37105
|
" memorix knowledge status",
|
|
37106
|
+
" memorix knowledge claims",
|
|
37107
|
+
' memorix knowledge review --id <claim-id> --review approved --detail "checked current source evidence"',
|
|
37002
37108
|
" memorix knowledge compile",
|
|
37003
37109
|
" memorix knowledge lint",
|
|
37004
37110
|
" memorix knowledge apply --proposal <id> [--force]",
|
|
@@ -37024,6 +37130,10 @@ function workflowVerdict(value) {
|
|
|
37024
37130
|
if (value === "passed" || value === "failed" || value === "not-run") return value;
|
|
37025
37131
|
throw new Error("workflow verdict must be passed, failed, or not-run");
|
|
37026
37132
|
}
|
|
37133
|
+
function claimReviewState(value) {
|
|
37134
|
+
if (value === "approved" || value === "rejected") return value;
|
|
37135
|
+
throw new Error("claim review must be approved or rejected");
|
|
37136
|
+
}
|
|
37027
37137
|
function evidenceList(value) {
|
|
37028
37138
|
if (typeof value !== "string" || !value.trim()) return [];
|
|
37029
37139
|
return [...new Set(value.split(",").map((item) => item.trim()).filter(Boolean))];
|
|
@@ -37036,6 +37146,7 @@ var init_knowledge = __esm({
|
|
|
37036
37146
|
init_dist2();
|
|
37037
37147
|
init_store();
|
|
37038
37148
|
init_claim_store();
|
|
37149
|
+
init_claims();
|
|
37039
37150
|
init_wiki();
|
|
37040
37151
|
init_workspace();
|
|
37041
37152
|
init_workspace_store();
|
|
@@ -37061,6 +37172,8 @@ var init_knowledge = __esm({
|
|
|
37061
37172
|
failure: { type: "string", description: "Sanitized failure reason for a workflow run" },
|
|
37062
37173
|
snapshot: { type: "string", description: "Starting code snapshot id for a workflow run" },
|
|
37063
37174
|
evidence: { type: "string", description: "Comma-separated evidence ids selected for a workflow run" },
|
|
37175
|
+
review: { type: "string", description: "Claim review verdict: approved or rejected" },
|
|
37176
|
+
detail: { type: "string", description: "Evidence check performed for a claim review" },
|
|
37064
37177
|
json: { type: "boolean", description: "Emit machine-readable JSON output" }
|
|
37065
37178
|
},
|
|
37066
37179
|
run: async ({ args }) => {
|
|
@@ -37096,6 +37209,34 @@ var init_knowledge = __esm({
|
|
|
37096
37209
|
await claimStore.init(dataDir);
|
|
37097
37210
|
const workspaceStore = new KnowledgeWorkspaceStore();
|
|
37098
37211
|
await workspaceStore.init(dataDir);
|
|
37212
|
+
if (action === "claims") {
|
|
37213
|
+
const claims = claimStore.listClaims(project.id, { limit: 100 });
|
|
37214
|
+
emitResult(
|
|
37215
|
+
{ project, workspace, claims },
|
|
37216
|
+
"Claims: " + claims.length + " total, " + claims.filter((claim) => claim.reviewState === "needs-review").length + " awaiting review.",
|
|
37217
|
+
asJson
|
|
37218
|
+
);
|
|
37219
|
+
return;
|
|
37220
|
+
}
|
|
37221
|
+
if (action === "review") {
|
|
37222
|
+
const claimId = requiredText2(args.id, "claim id");
|
|
37223
|
+
const existing = claimStore.getClaim(claimId);
|
|
37224
|
+
if (!existing || existing.projectId !== project.id) {
|
|
37225
|
+
emitError("Claim was not found for this knowledge workspace.", asJson);
|
|
37226
|
+
return;
|
|
37227
|
+
}
|
|
37228
|
+
const claim = reviewClaim(claimStore, {
|
|
37229
|
+
claimId,
|
|
37230
|
+
reviewState: claimReviewState(args.review),
|
|
37231
|
+
detail: requiredText2(args.detail, "review detail")
|
|
37232
|
+
});
|
|
37233
|
+
emitResult(
|
|
37234
|
+
{ project, workspace, claim },
|
|
37235
|
+
"Claim " + claim.id + " marked " + claim.reviewState + ".",
|
|
37236
|
+
asJson
|
|
37237
|
+
);
|
|
37238
|
+
return;
|
|
37239
|
+
}
|
|
37099
37240
|
if (action === "workflow") {
|
|
37100
37241
|
const workflowAction = (positional[1] || "list").toLowerCase();
|
|
37101
37242
|
const workflowStore = new WorkflowStore();
|
|
@@ -64407,6 +64548,24 @@ async function createAutoRelations(obs, extracted, graphManager) {
|
|
|
64407
64548
|
const relationType = inferRelationType(obs);
|
|
64408
64549
|
const relations = [];
|
|
64409
64550
|
const selfName = obs.entityName.toLowerCase();
|
|
64551
|
+
const explicitRelated = [...new Set((obs.relatedEntities ?? []).map((name) => name.trim()).filter((name) => name && name.toLowerCase() !== selfName))];
|
|
64552
|
+
if (explicitRelated.length > 0) {
|
|
64553
|
+
await graphManager.createEntities(explicitRelated.map((name) => ({
|
|
64554
|
+
name,
|
|
64555
|
+
entityType: "related",
|
|
64556
|
+
observations: []
|
|
64557
|
+
})));
|
|
64558
|
+
for (const name of explicitRelated) {
|
|
64559
|
+
const matchedEntity = graphManager.findEntityByName(name);
|
|
64560
|
+
if (matchedEntity) {
|
|
64561
|
+
relations.push({
|
|
64562
|
+
from: obs.entityName,
|
|
64563
|
+
to: matchedEntity.name,
|
|
64564
|
+
relationType: "related_entity"
|
|
64565
|
+
});
|
|
64566
|
+
}
|
|
64567
|
+
}
|
|
64568
|
+
}
|
|
64410
64569
|
const candidates = [
|
|
64411
64570
|
...extracted.identifiers,
|
|
64412
64571
|
...extracted.files.map((f4) => f4.split("/").pop()?.replace(/\.\w+$/, "") ?? ""),
|
|
@@ -64452,6 +64611,36 @@ var init_auto_relations = __esm({
|
|
|
64452
64611
|
}
|
|
64453
64612
|
});
|
|
64454
64613
|
|
|
64614
|
+
// src/memory/graph-scope.ts
|
|
64615
|
+
function projectGraphEntityNames(observations2) {
|
|
64616
|
+
const entityNames = /* @__PURE__ */ new Set();
|
|
64617
|
+
for (const observation of observations2) {
|
|
64618
|
+
if ((observation.status ?? "active") !== "active") continue;
|
|
64619
|
+
const entityName = observation.entityName?.trim();
|
|
64620
|
+
if (entityName) entityNames.add(entityName);
|
|
64621
|
+
for (const relatedEntity of observation.relatedEntities ?? []) {
|
|
64622
|
+
const name = relatedEntity.trim();
|
|
64623
|
+
if (name) entityNames.add(name);
|
|
64624
|
+
}
|
|
64625
|
+
}
|
|
64626
|
+
return entityNames;
|
|
64627
|
+
}
|
|
64628
|
+
function scopeKnowledgeGraphToProject(graph, observations2) {
|
|
64629
|
+
const entityNames = projectGraphEntityNames(observations2);
|
|
64630
|
+
const entities = graph.entities.filter((entity) => entityNames.has(entity.name));
|
|
64631
|
+
const visibleNames = new Set(entities.map((entity) => entity.name));
|
|
64632
|
+
const relations = graph.relations.filter(
|
|
64633
|
+
(relation) => visibleNames.has(relation.from) && visibleNames.has(relation.to)
|
|
64634
|
+
);
|
|
64635
|
+
return { entities, relations, entityNames };
|
|
64636
|
+
}
|
|
64637
|
+
var init_graph_scope = __esm({
|
|
64638
|
+
"src/memory/graph-scope.ts"() {
|
|
64639
|
+
"use strict";
|
|
64640
|
+
init_esm_shims();
|
|
64641
|
+
}
|
|
64642
|
+
});
|
|
64643
|
+
|
|
64455
64644
|
// src/rules/utils.ts
|
|
64456
64645
|
import { createHash as createHash13 } from "crypto";
|
|
64457
64646
|
function hashContent2(content) {
|
|
@@ -67157,13 +67346,8 @@ function prepareDashboardConfig(projectRoot) {
|
|
|
67157
67346
|
}
|
|
67158
67347
|
}
|
|
67159
67348
|
function computeProjectGraphCounts(allEntities, allRelations, projectObs) {
|
|
67160
|
-
const
|
|
67161
|
-
|
|
67162
|
-
);
|
|
67163
|
-
const entities = allEntities.filter((e3) => entityNames.has(e3.name));
|
|
67164
|
-
const entityNameSet = new Set(entities.map((e3) => e3.name));
|
|
67165
|
-
const relations = allRelations.filter((r4) => entityNameSet.has(r4.from) && entityNameSet.has(r4.to));
|
|
67166
|
-
return { entities: entities.length, relations: relations.length, entityNames };
|
|
67349
|
+
const scoped = scopeKnowledgeGraphToProject({ entities: allEntities, relations: allRelations }, projectObs);
|
|
67350
|
+
return { entities: scoped.entities.length, relations: scoped.relations.length, entityNames: scoped.entityNames };
|
|
67167
67351
|
}
|
|
67168
67352
|
async function handleApi(req, res, dataDir, projectId, projectName, baseDir, projectRoot, projectResolved, mode = "standalone", port = 3210) {
|
|
67169
67353
|
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
@@ -67236,13 +67420,8 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
67236
67420
|
const gStore = getGraphStore();
|
|
67237
67421
|
const graph = { entities: gStore.loadEntities(), relations: gStore.loadRelations() };
|
|
67238
67422
|
const graphObs = await getObservationStore().loadByProject(effectiveProjectId, { status: "active" });
|
|
67239
|
-
const
|
|
67240
|
-
|
|
67241
|
-
);
|
|
67242
|
-
const entities = graph.entities.filter((e3) => projectEntityNames.has(e3.name));
|
|
67243
|
-
const entityNameSet = new Set(entities.map((e3) => e3.name));
|
|
67244
|
-
const relations = graph.relations.filter((r4) => entityNameSet.has(r4.from) && entityNameSet.has(r4.to));
|
|
67245
|
-
sendJson(res, { entities, relations });
|
|
67423
|
+
const scoped = scopeKnowledgeGraphToProject(graph, graphObs);
|
|
67424
|
+
sendJson(res, { entities: scoped.entities, relations: scoped.relations });
|
|
67246
67425
|
break;
|
|
67247
67426
|
}
|
|
67248
67427
|
case "/observations": {
|
|
@@ -67434,19 +67613,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
67434
67613
|
const allObs = await getObservationStore().loadByProject(effectiveProjectId, { status: "active" });
|
|
67435
67614
|
const skills = await getMiniSkillStore2().loadByProject(effectiveProjectId);
|
|
67436
67615
|
const fullGraph = { entities: getGraphStore2().loadEntities(), relations: getGraphStore2().loadRelations() };
|
|
67437
|
-
const
|
|
67438
|
-
const projectEntityNames = new Set(
|
|
67439
|
-
graphObs.filter((o3) => o3.entityName).map((o3) => o3.entityName)
|
|
67440
|
-
);
|
|
67441
|
-
const scopedEntities = fullGraph.entities.filter((e3) => projectEntityNames.has(e3.name));
|
|
67442
|
-
const scopedEntityNameSet = new Set(scopedEntities.map((e3) => e3.name));
|
|
67443
|
-
const scopedRelations = fullGraph.relations.filter((r4) => scopedEntityNameSet.has(r4.from) && scopedEntityNameSet.has(r4.to));
|
|
67616
|
+
const scoped = scopeKnowledgeGraphToProject(fullGraph, allObs);
|
|
67444
67617
|
const graph = generateKnowledgeGraph2({
|
|
67445
67618
|
projectId: effectiveProjectId,
|
|
67446
67619
|
observations: allObs,
|
|
67447
67620
|
miniSkills: skills,
|
|
67448
|
-
graphEntities:
|
|
67449
|
-
graphRelations:
|
|
67621
|
+
graphEntities: scoped.entities,
|
|
67622
|
+
graphRelations: scoped.relations
|
|
67450
67623
|
});
|
|
67451
67624
|
sendJson(res, graph);
|
|
67452
67625
|
break;
|
|
@@ -67668,16 +67841,11 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
|
|
|
67668
67841
|
const fullGraph = { entities: getGraphStore().loadEntities(), relations: getGraphStore().loadRelations() };
|
|
67669
67842
|
const observations2 = await getObservationStore().loadByProject(effectiveProjectId, { status: "active" });
|
|
67670
67843
|
const nextId2 = await getObservationStore().loadIdCounter();
|
|
67671
|
-
const
|
|
67672
|
-
observations2.filter((o3) => (o3.status ?? "active") === "active" && o3.entityName).map((o3) => o3.entityName)
|
|
67673
|
-
);
|
|
67674
|
-
const exportEntities = fullGraph.entities.filter((e3) => exportEntityNames.has(e3.name));
|
|
67675
|
-
const exportEntitySet = new Set(exportEntities.map((e3) => e3.name));
|
|
67676
|
-
const exportRelations = fullGraph.relations.filter((r4) => exportEntitySet.has(r4.from) && exportEntitySet.has(r4.to));
|
|
67844
|
+
const scoped = scopeKnowledgeGraphToProject(fullGraph, observations2);
|
|
67677
67845
|
const exportData = {
|
|
67678
67846
|
project: { id: effectiveProjectId, name: effectiveProjectName },
|
|
67679
67847
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
67680
|
-
graph: { entities:
|
|
67848
|
+
graph: { entities: scoped.entities, relations: scoped.relations },
|
|
67681
67849
|
observations: observations2,
|
|
67682
67850
|
nextId: nextId2
|
|
67683
67851
|
};
|
|
@@ -67994,6 +68162,7 @@ var init_server3 = __esm({
|
|
|
67994
68162
|
init_dotenv_loader();
|
|
67995
68163
|
init_yaml_loader();
|
|
67996
68164
|
init_yaml_loader();
|
|
68165
|
+
init_graph_scope();
|
|
67997
68166
|
MIME_TYPES = {
|
|
67998
68167
|
".html": "text/html; charset=utf-8",
|
|
67999
68168
|
".css": "text/css; charset=utf-8",
|
|
@@ -68571,7 +68740,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
68571
68740
|
};
|
|
68572
68741
|
const server = existingServer ?? new McpServer({
|
|
68573
68742
|
name: "memorix",
|
|
68574
|
-
version: true ? "1.2.
|
|
68743
|
+
version: true ? "1.2.1" : "1.0.1"
|
|
68575
68744
|
});
|
|
68576
68745
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
68577
68746
|
server.registerTool = ((name, ...args) => {
|
|
@@ -69303,7 +69472,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69303
69472
|
{ getResolvedConfig: getResolvedConfig2 },
|
|
69304
69473
|
{ getExternalCodeGraphContext: getExternalCodeGraphContext2 },
|
|
69305
69474
|
{ getObservationStore: getObservationStore2 },
|
|
69306
|
-
{ collectCurrentProjectFacts: collectCurrentProjectFacts2 },
|
|
69475
|
+
{ collectCurrentProjectFacts: collectCurrentProjectFacts2, formatGitFact: formatGitFact2 },
|
|
69307
69476
|
{ resolveTaskLens: resolveTaskLens2 }
|
|
69308
69477
|
] = await Promise.all([
|
|
69309
69478
|
Promise.resolve().then(() => (init_store(), store_exports)),
|
|
@@ -69344,7 +69513,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69344
69513
|
if (currentFacts.latestChangelog) {
|
|
69345
69514
|
worksetFacts.push("Latest changelog: " + currentFacts.latestChangelog.version + (currentFacts.latestChangelog.date ? " (" + currentFacts.latestChangelog.date + ")" : ""));
|
|
69346
69515
|
}
|
|
69347
|
-
worksetFacts.push(
|
|
69516
|
+
worksetFacts.push(formatGitFact2(currentFacts.git));
|
|
69348
69517
|
const codeState = snapshot ? "- Code state: " + (snapshot.baseRevision ? snapshot.baseRevision.slice(0, 12) : "Git unavailable") + ", " + snapshot.worktreeState + " worktree, epoch " + snapshot.sourceEpoch : "- Code state: no completed snapshot yet";
|
|
69349
69518
|
const pack = await attachTaskWorkset2({
|
|
69350
69519
|
pack: basePack,
|
|
@@ -69376,11 +69545,13 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69376
69545
|
"memorix_knowledge",
|
|
69377
69546
|
{
|
|
69378
69547
|
title: "Knowledge Workspace",
|
|
69379
|
-
description: "Manage the reviewable project Knowledge Workspace. Use it only for deliberate knowledge operations: initialize a local or versioned workspace,
|
|
69548
|
+
description: "Manage the reviewable project Knowledge Workspace. Use it only for deliberate knowledge operations: initialize a local or versioned workspace, review source-backed claims, compile proposals, lint, apply a reviewed proposal, or manage canonical workflows. It is intentionally absent from the default micro/lite profiles.",
|
|
69380
69549
|
inputSchema: {
|
|
69381
69550
|
action: external_exports.enum([
|
|
69382
69551
|
"workspace_init",
|
|
69383
69552
|
"status",
|
|
69553
|
+
"claim_list",
|
|
69554
|
+
"claim_review",
|
|
69384
69555
|
"compile",
|
|
69385
69556
|
"lint",
|
|
69386
69557
|
"proposal_apply",
|
|
@@ -69395,6 +69566,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69395
69566
|
path: external_exports.string().optional().describe("Explicit versioned workspace path, used only by workspace_init"),
|
|
69396
69567
|
proposalId: external_exports.string().optional().describe("Pending proposal id for proposal_apply"),
|
|
69397
69568
|
allowManualOverwrite: external_exports.boolean().optional().default(false).describe("Explicitly allow proposal_apply to replace a manually edited page"),
|
|
69569
|
+
claimId: external_exports.string().optional().describe("Source-backed claim id for claim_review"),
|
|
69570
|
+
claimReviewState: external_exports.enum(["approved", "rejected"]).optional().describe("Deliberate review verdict for claim_review"),
|
|
69571
|
+
reviewDetail: external_exports.string().max(2e3).optional().describe("Evidence check performed before approving or rejecting a claim"),
|
|
69398
69572
|
workflowId: external_exports.string().optional().describe("Canonical workflow id for workflow preview, apply, or run"),
|
|
69399
69573
|
agent: external_exports.string().optional().describe("Target agent for a workflow adapter"),
|
|
69400
69574
|
task: external_exports.string().optional().describe("Task text for workflow selection or a workflow run"),
|
|
@@ -69411,6 +69585,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69411
69585
|
path: workspacePath,
|
|
69412
69586
|
proposalId,
|
|
69413
69587
|
allowManualOverwrite,
|
|
69588
|
+
claimId,
|
|
69589
|
+
claimReviewState: claimReviewState2,
|
|
69590
|
+
reviewDetail,
|
|
69414
69591
|
workflowId,
|
|
69415
69592
|
agent,
|
|
69416
69593
|
task,
|
|
@@ -69433,6 +69610,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69433
69610
|
};
|
|
69434
69611
|
const [
|
|
69435
69612
|
{ ClaimStore: ClaimStore2 },
|
|
69613
|
+
{ reviewClaim: reviewClaim2 },
|
|
69436
69614
|
{ CodeGraphStore: CodeGraphStore2 },
|
|
69437
69615
|
{ initializeKnowledgeWorkspace: initializeKnowledgeWorkspace2, loadKnowledgeWorkspace: loadKnowledgeWorkspace2 },
|
|
69438
69616
|
{ KnowledgeWorkspaceStore: KnowledgeWorkspaceStore2 },
|
|
@@ -69448,6 +69626,7 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69448
69626
|
}
|
|
69449
69627
|
] = await Promise.all([
|
|
69450
69628
|
Promise.resolve().then(() => (init_claim_store(), claim_store_exports)),
|
|
69629
|
+
Promise.resolve().then(() => (init_claims(), claims_exports)),
|
|
69451
69630
|
Promise.resolve().then(() => (init_store(), store_exports)),
|
|
69452
69631
|
Promise.resolve().then(() => (init_workspace(), workspace_exports)),
|
|
69453
69632
|
Promise.resolve().then(() => (init_workspace_store(), workspace_store_exports)),
|
|
@@ -69497,10 +69676,52 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69497
69676
|
targetPath: proposal.targetPath,
|
|
69498
69677
|
reason: proposal.reason,
|
|
69499
69678
|
createdAt: proposal.createdAt
|
|
69500
|
-
}))
|
|
69679
|
+
})),
|
|
69680
|
+
reviewableClaims: claims.listClaims(project.id, { limit: 100 }).filter((claim) => claim.reviewState === "needs-review").map((claim) => ({ id: claim.id, subject: claim.subject, predicate: claim.predicate, objectValue: claim.objectValue }))
|
|
69501
69681
|
}
|
|
69502
69682
|
});
|
|
69503
69683
|
}
|
|
69684
|
+
if (action === "claim_list") {
|
|
69685
|
+
return text({
|
|
69686
|
+
claims: claims.listClaims(project.id, { limit: 100 }).map((claim) => ({
|
|
69687
|
+
id: claim.id,
|
|
69688
|
+
subject: claim.subject,
|
|
69689
|
+
predicate: claim.predicate,
|
|
69690
|
+
objectValue: claim.objectValue,
|
|
69691
|
+
status: claim.status,
|
|
69692
|
+
reviewState: claim.reviewState,
|
|
69693
|
+
origin: claim.origin,
|
|
69694
|
+
confidence: claim.confidence,
|
|
69695
|
+
evidenceCount: claims.listEvidence(claim.id).length
|
|
69696
|
+
})),
|
|
69697
|
+
next: "Approve only after checking the linked evidence. Rejected claims stay out of retrieval and publication."
|
|
69698
|
+
});
|
|
69699
|
+
}
|
|
69700
|
+
if (action === "claim_review") {
|
|
69701
|
+
const requestedClaimId = requireText(claimId, "claimId");
|
|
69702
|
+
const detail = requireText(reviewDetail, "reviewDetail");
|
|
69703
|
+
if (!requestedClaimId || !claimReviewState2 || !detail) {
|
|
69704
|
+
return text({ error: "claimId, claimReviewState, and reviewDetail are required for claim_review." }, true);
|
|
69705
|
+
}
|
|
69706
|
+
const existing = claims.getClaim(requestedClaimId);
|
|
69707
|
+
if (!existing || existing.projectId !== project.id) {
|
|
69708
|
+
return text({ error: "Claim was not found for the current project." }, true);
|
|
69709
|
+
}
|
|
69710
|
+
const claim = reviewClaim2(claims, {
|
|
69711
|
+
claimId: requestedClaimId,
|
|
69712
|
+
reviewState: claimReviewState2,
|
|
69713
|
+
detail
|
|
69714
|
+
});
|
|
69715
|
+
return text({
|
|
69716
|
+
claim: {
|
|
69717
|
+
id: claim.id,
|
|
69718
|
+
status: claim.status,
|
|
69719
|
+
reviewState: claim.reviewState,
|
|
69720
|
+
updatedAt: claim.updatedAt
|
|
69721
|
+
},
|
|
69722
|
+
next: claim.reviewState === "approved" ? "This approved source-backed claim can now be considered by knowledge compilation." : "This rejected claim is excluded from retrieval and knowledge compilation."
|
|
69723
|
+
});
|
|
69724
|
+
}
|
|
69504
69725
|
if (action === "compile") {
|
|
69505
69726
|
const result = await compileKnowledgeWorkspace2({ workspace, claims });
|
|
69506
69727
|
return text({
|
|
@@ -69539,7 +69760,13 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69539
69760
|
if (action === "workflow_import") {
|
|
69540
69761
|
const result = await importWindsurfWorkflows2({ workspace, projectRoot });
|
|
69541
69762
|
return text({
|
|
69542
|
-
imported: result.imported.map((workflow2) => ({
|
|
69763
|
+
imported: result.imported.map((workflow2) => ({
|
|
69764
|
+
id: workflow2.id,
|
|
69765
|
+
title: workflow2.title,
|
|
69766
|
+
sourcePath: workflow2.sourcePath,
|
|
69767
|
+
importedFrom: workflow2.importedFrom,
|
|
69768
|
+
verificationGates: workflow2.verificationGates
|
|
69769
|
+
})),
|
|
69543
69770
|
skipped: result.skipped
|
|
69544
69771
|
});
|
|
69545
69772
|
}
|
|
@@ -69551,7 +69778,9 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
|
|
|
69551
69778
|
title: workflow2.title,
|
|
69552
69779
|
status: workflow2.status,
|
|
69553
69780
|
taskLenses: workflow2.taskLenses,
|
|
69554
|
-
sourcePath: workflow2.sourcePath
|
|
69781
|
+
sourcePath: workflow2.sourcePath,
|
|
69782
|
+
importedFrom: workflow2.importedFrom,
|
|
69783
|
+
verificationGates: workflow2.verificationGates
|
|
69555
69784
|
})),
|
|
69556
69785
|
parseErrors: synced.errors
|
|
69557
69786
|
});
|
|
@@ -70380,13 +70609,11 @@ Archived memories are hidden from default search but can be found with status: "
|
|
|
70380
70609
|
async function scopeGraphToProject(graph) {
|
|
70381
70610
|
const { getAllObservations: getAllObservations2 } = await Promise.resolve().then(() => (init_observations(), observations_exports));
|
|
70382
70611
|
const allObs = await withFreshIndex(() => getAllObservations2());
|
|
70383
|
-
const
|
|
70384
|
-
|
|
70612
|
+
const scoped = scopeKnowledgeGraphToProject(
|
|
70613
|
+
graph,
|
|
70614
|
+
allObs.filter((observation) => observation.projectId === project.id)
|
|
70385
70615
|
);
|
|
70386
|
-
|
|
70387
|
-
const entityNameSet = new Set(entities.map((e3) => e3.name));
|
|
70388
|
-
const relations = graph.relations.filter((r4) => entityNameSet.has(r4.from) && entityNameSet.has(r4.to));
|
|
70389
|
-
return { entities, relations };
|
|
70616
|
+
return { entities: scoped.entities, relations: scoped.relations };
|
|
70390
70617
|
}
|
|
70391
70618
|
server.registerTool(
|
|
70392
70619
|
"read_graph",
|
|
@@ -71986,6 +72213,7 @@ var init_server4 = __esm({
|
|
|
71986
72213
|
init_attribution_guard();
|
|
71987
72214
|
init_auto_relations();
|
|
71988
72215
|
init_entity_extractor();
|
|
72216
|
+
init_graph_scope();
|
|
71989
72217
|
init_engine();
|
|
71990
72218
|
init_graph_context();
|
|
71991
72219
|
init_detector();
|
|
@@ -73916,6 +74144,7 @@ var init_serve_http = __esm({
|
|
|
73916
74144
|
init_esm_shims();
|
|
73917
74145
|
init_dist2();
|
|
73918
74146
|
init_tool_profile();
|
|
74147
|
+
init_graph_scope();
|
|
73919
74148
|
DEFAULT_SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
73920
74149
|
serve_http_default = defineCommand({
|
|
73921
74150
|
meta: {
|
|
@@ -74546,12 +74775,7 @@ var init_serve_http = __esm({
|
|
|
74546
74775
|
}
|
|
74547
74776
|
} catch {
|
|
74548
74777
|
}
|
|
74549
|
-
const
|
|
74550
|
-
observations2.filter((o3) => o3.entityName).map((o3) => o3.entityName)
|
|
74551
|
-
);
|
|
74552
|
-
const projectEntities = graph.entities.filter((e3) => projectEntityNames.has(e3.name));
|
|
74553
|
-
const projectEntitySet = new Set(projectEntities.map((e3) => e3.name));
|
|
74554
|
-
const projectRelations = graph.relations.filter((r4) => projectEntitySet.has(r4.from) && projectEntitySet.has(r4.to));
|
|
74778
|
+
const projectGraph = scopeKnowledgeGraphToProject(graph, observations2);
|
|
74555
74779
|
let maintenance = { total: 0, pending: 0, running: 0, retrying: 0, completed: 0, failed: 0 };
|
|
74556
74780
|
let lifecycle;
|
|
74557
74781
|
try {
|
|
@@ -74562,8 +74786,8 @@ var init_serve_http = __esm({
|
|
|
74562
74786
|
} catch {
|
|
74563
74787
|
}
|
|
74564
74788
|
sendJson2({
|
|
74565
|
-
entities:
|
|
74566
|
-
relations:
|
|
74789
|
+
entities: projectGraph.entities.length,
|
|
74790
|
+
relations: projectGraph.relations.length,
|
|
74567
74791
|
observations: observations2.length,
|
|
74568
74792
|
nextId: nextId2,
|
|
74569
74793
|
typeCounts,
|
|
@@ -74612,13 +74836,8 @@ var init_serve_http = __esm({
|
|
|
74612
74836
|
await initGraphStore2(graphDataDir);
|
|
74613
74837
|
const fullGraph = { entities: getGraphStore2().loadEntities(), relations: getGraphStore2().loadRelations() };
|
|
74614
74838
|
const allObs = await loadDashboardProjectObservations(graphDataDir, graphProjectId, "active");
|
|
74615
|
-
const
|
|
74616
|
-
|
|
74617
|
-
);
|
|
74618
|
-
const entities = fullGraph.entities.filter((e3) => projectEntityNames.has(e3.name));
|
|
74619
|
-
const entityNameSet = new Set(entities.map((e3) => e3.name));
|
|
74620
|
-
const relations = fullGraph.relations.filter((r4) => entityNameSet.has(r4.from) && entityNameSet.has(r4.to));
|
|
74621
|
-
sendJson2({ entities, relations });
|
|
74839
|
+
const scoped = scopeKnowledgeGraphToProject(fullGraph, allObs);
|
|
74840
|
+
sendJson2({ entities: scoped.entities, relations: scoped.relations });
|
|
74622
74841
|
return;
|
|
74623
74842
|
}
|
|
74624
74843
|
if (apiPath === "/sessions") {
|
|
@@ -74678,19 +74897,13 @@ var init_serve_http = __esm({
|
|
|
74678
74897
|
const allObs = await loadDashboardProjectObservations(kgDataDir, kgProjectId, "active");
|
|
74679
74898
|
const skills = await getMiniSkillStore2().loadByProject(kgProjectId);
|
|
74680
74899
|
const fullGraph = { entities: getGraphStore2().loadEntities(), relations: getGraphStore2().loadRelations() };
|
|
74681
|
-
const
|
|
74682
|
-
const projectEntityNames = new Set(
|
|
74683
|
-
graphObs.filter((o3) => o3.entityName).map((o3) => o3.entityName)
|
|
74684
|
-
);
|
|
74685
|
-
const scopedEntities = fullGraph.entities.filter((e3) => projectEntityNames.has(e3.name));
|
|
74686
|
-
const scopedEntityNameSet = new Set(scopedEntities.map((e3) => e3.name));
|
|
74687
|
-
const scopedRelations = fullGraph.relations.filter((r4) => scopedEntityNameSet.has(r4.from) && scopedEntityNameSet.has(r4.to));
|
|
74900
|
+
const scoped = scopeKnowledgeGraphToProject(fullGraph, allObs);
|
|
74688
74901
|
const graph = generateKnowledgeGraph2({
|
|
74689
74902
|
projectId: kgProjectId,
|
|
74690
74903
|
observations: allObs,
|
|
74691
74904
|
miniSkills: skills,
|
|
74692
|
-
graphEntities:
|
|
74693
|
-
graphRelations:
|
|
74905
|
+
graphEntities: scoped.entities,
|
|
74906
|
+
graphRelations: scoped.relations
|
|
74694
74907
|
});
|
|
74695
74908
|
sendJson2(graph);
|
|
74696
74909
|
return;
|
|
@@ -74966,16 +75179,11 @@ var init_serve_http = __esm({
|
|
|
74966
75179
|
const observations2 = await loadDashboardProjectObservations(expDataDir, expProjectId, "active");
|
|
74967
75180
|
const expStore = await getDashboardObservationStore(expDataDir);
|
|
74968
75181
|
const nextId2 = await expStore.loadIdCounter();
|
|
74969
|
-
const
|
|
74970
|
-
observations2.filter((o3) => o3.entityName).map((o3) => o3.entityName)
|
|
74971
|
-
);
|
|
74972
|
-
const exportEntities = fullGraph.entities.filter((e3) => exportEntityNames.has(e3.name));
|
|
74973
|
-
const exportEntitySet = new Set(exportEntities.map((e3) => e3.name));
|
|
74974
|
-
const exportRelations = fullGraph.relations.filter((r4) => exportEntitySet.has(r4.from) && exportEntitySet.has(r4.to));
|
|
75182
|
+
const scoped = scopeKnowledgeGraphToProject(fullGraph, observations2);
|
|
74975
75183
|
const exportData = {
|
|
74976
75184
|
project: { id: expProjectId, name: expProjectName },
|
|
74977
75185
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
74978
|
-
graph: { entities:
|
|
75186
|
+
graph: { entities: scoped.entities, relations: scoped.relations },
|
|
74979
75187
|
observations: observations2,
|
|
74980
75188
|
nextId: nextId2
|
|
74981
75189
|
};
|
|
@@ -77101,8 +77309,8 @@ async function installSingleAgent2(agent, cwd, global2) {
|
|
|
77101
77309
|
console.log(` Events: ${config2.events.join(", ")}`);
|
|
77102
77310
|
if (agent === "copilot" && process.platform === "win32") {
|
|
77103
77311
|
try {
|
|
77104
|
-
const { execSync:
|
|
77105
|
-
|
|
77312
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
77313
|
+
execSync10("pwsh --version", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "ignore"] });
|
|
77106
77314
|
} catch {
|
|
77107
77315
|
console.warn(`[WARN] ${agent}: pwsh (PowerShell v7+) not found. Copilot hooks will use the bash field via Git Bash.`);
|
|
77108
77316
|
console.warn(` For best Windows support, install PowerShell v7+: winget install Microsoft.PowerShell`);
|
|
@@ -79826,7 +80034,7 @@ var init_doctor = __esm({
|
|
|
79826
80034
|
const { existsSync: existsSync29, readFileSync: readFileSync23 } = await import("fs");
|
|
79827
80035
|
const { join: join32, basename: basename5 } = await import("path");
|
|
79828
80036
|
const { homedir: homedir34 } = await import("os");
|
|
79829
|
-
const { execSync:
|
|
80037
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
79830
80038
|
const report = {};
|
|
79831
80039
|
const issues = [];
|
|
79832
80040
|
const tips = [];
|
|
@@ -82449,12 +82657,20 @@ var init_worktree = __esm({
|
|
|
82449
82657
|
});
|
|
82450
82658
|
|
|
82451
82659
|
// src/orchestrate/verify-gate.ts
|
|
82452
|
-
import { spawn as spawn4
|
|
82660
|
+
import { spawn as spawn4 } from "child_process";
|
|
82453
82661
|
function runGate(gate, command, cwd, timeoutMs, outputBudget = DEFAULT_OUTPUT_BUDGET) {
|
|
82454
82662
|
const start = Date.now();
|
|
82455
82663
|
return new Promise((resolve5) => {
|
|
82456
82664
|
const chunks = [];
|
|
82457
82665
|
let totalBytes = 0;
|
|
82666
|
+
let settled = false;
|
|
82667
|
+
let timer;
|
|
82668
|
+
const finish = (result) => {
|
|
82669
|
+
if (settled) return;
|
|
82670
|
+
settled = true;
|
|
82671
|
+
if (timer) clearTimeout(timer);
|
|
82672
|
+
resolve5(result);
|
|
82673
|
+
};
|
|
82458
82674
|
const proc = spawn4(command, {
|
|
82459
82675
|
cwd,
|
|
82460
82676
|
shell: true,
|
|
@@ -82474,8 +82690,12 @@ function runGate(gate, command, cwd, timeoutMs, outputBudget = DEFAULT_OUTPUT_BU
|
|
|
82474
82690
|
let killed = false;
|
|
82475
82691
|
const killTree = () => {
|
|
82476
82692
|
try {
|
|
82477
|
-
if (process.platform === "win32") {
|
|
82478
|
-
|
|
82693
|
+
if (process.platform === "win32" && proc.pid) {
|
|
82694
|
+
const killer = spawn4("taskkill.exe", ["/F", "/T", "/PID", String(proc.pid)], {
|
|
82695
|
+
stdio: "ignore",
|
|
82696
|
+
windowsHide: true
|
|
82697
|
+
});
|
|
82698
|
+
killer.unref();
|
|
82479
82699
|
} else {
|
|
82480
82700
|
process.kill(-proc.pid, "SIGKILL");
|
|
82481
82701
|
}
|
|
@@ -82485,17 +82705,34 @@ function runGate(gate, command, cwd, timeoutMs, outputBudget = DEFAULT_OUTPUT_BU
|
|
|
82485
82705
|
} catch {
|
|
82486
82706
|
}
|
|
82487
82707
|
}
|
|
82708
|
+
try {
|
|
82709
|
+
proc.stdout?.destroy();
|
|
82710
|
+
} catch {
|
|
82711
|
+
}
|
|
82712
|
+
try {
|
|
82713
|
+
proc.stderr?.destroy();
|
|
82714
|
+
} catch {
|
|
82715
|
+
}
|
|
82716
|
+
proc.unref();
|
|
82488
82717
|
};
|
|
82489
|
-
|
|
82718
|
+
timer = setTimeout(() => {
|
|
82490
82719
|
killed = true;
|
|
82491
82720
|
killTree();
|
|
82721
|
+
const output = Buffer.concat(chunks).toString("utf-8");
|
|
82722
|
+
finish({
|
|
82723
|
+
gate,
|
|
82724
|
+
passed: false,
|
|
82725
|
+
output: output + `
|
|
82726
|
+
[TIMEOUT] Gate "${gate}" killed after ${timeoutMs}ms`,
|
|
82727
|
+
durationMs: Date.now() - start,
|
|
82728
|
+
command
|
|
82729
|
+
});
|
|
82492
82730
|
}, timeoutMs);
|
|
82493
82731
|
proc.on("close", (code) => {
|
|
82494
|
-
clearTimeout(timer);
|
|
82495
82732
|
const output = Buffer.concat(chunks).toString("utf-8");
|
|
82496
82733
|
const durationMs = Date.now() - start;
|
|
82497
82734
|
if (killed) {
|
|
82498
|
-
|
|
82735
|
+
finish({
|
|
82499
82736
|
gate,
|
|
82500
82737
|
passed: false,
|
|
82501
82738
|
output: output + `
|
|
@@ -82505,7 +82742,7 @@ function runGate(gate, command, cwd, timeoutMs, outputBudget = DEFAULT_OUTPUT_BU
|
|
|
82505
82742
|
});
|
|
82506
82743
|
return;
|
|
82507
82744
|
}
|
|
82508
|
-
|
|
82745
|
+
finish({
|
|
82509
82746
|
gate,
|
|
82510
82747
|
passed: code === 0,
|
|
82511
82748
|
output,
|
|
@@ -82514,8 +82751,7 @@ function runGate(gate, command, cwd, timeoutMs, outputBudget = DEFAULT_OUTPUT_BU
|
|
|
82514
82751
|
});
|
|
82515
82752
|
});
|
|
82516
82753
|
proc.on("error", (err) => {
|
|
82517
|
-
|
|
82518
|
-
resolve5({
|
|
82754
|
+
finish({
|
|
82519
82755
|
gate,
|
|
82520
82756
|
passed: false,
|
|
82521
82757
|
output: `[ERROR] Failed to spawn gate command: ${err.message}`,
|
|
@@ -83169,7 +83405,7 @@ var coordinator_exports = {};
|
|
|
83169
83405
|
__export(coordinator_exports, {
|
|
83170
83406
|
runCoordinationLoop: () => runCoordinationLoop
|
|
83171
83407
|
});
|
|
83172
|
-
import { execSync as
|
|
83408
|
+
import { execSync as execSync8 } from "child_process";
|
|
83173
83409
|
async function runCoordinationLoop(config2) {
|
|
83174
83410
|
const {
|
|
83175
83411
|
projectDir: projectDir2,
|
|
@@ -84110,7 +84346,7 @@ function sleep3(ms) {
|
|
|
84110
84346
|
}
|
|
84111
84347
|
function isGitRepository(projectDir2) {
|
|
84112
84348
|
try {
|
|
84113
|
-
|
|
84349
|
+
execSync8("git rev-parse --is-inside-work-tree", {
|
|
84114
84350
|
cwd: projectDir2,
|
|
84115
84351
|
encoding: "utf-8",
|
|
84116
84352
|
timeout: 5e3,
|
|
@@ -84123,7 +84359,7 @@ function isGitRepository(projectDir2) {
|
|
|
84123
84359
|
}
|
|
84124
84360
|
function getGitStatus(projectDir2) {
|
|
84125
84361
|
try {
|
|
84126
|
-
return
|
|
84362
|
+
return execSync8("git status --porcelain", {
|
|
84127
84363
|
cwd: projectDir2,
|
|
84128
84364
|
encoding: "utf-8",
|
|
84129
84365
|
timeout: 5e3,
|
|
@@ -88532,19 +88768,19 @@ ${hookScript}`, "utf-8");
|
|
|
88532
88768
|
const handleBackgroundAction = useCallback5(async (action) => {
|
|
88533
88769
|
setStatusMsg(null);
|
|
88534
88770
|
try {
|
|
88535
|
-
const { execSync:
|
|
88771
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
88536
88772
|
if (background.running) {
|
|
88537
88773
|
switch (action) {
|
|
88538
88774
|
case "w":
|
|
88539
88775
|
if (background.dashboard) {
|
|
88540
88776
|
try {
|
|
88541
|
-
|
|
88777
|
+
execSync10(`start "" "${background.dashboard}"`, { stdio: "pipe" });
|
|
88542
88778
|
} catch {
|
|
88543
88779
|
try {
|
|
88544
|
-
|
|
88780
|
+
execSync10(`open "${background.dashboard}"`, { stdio: "pipe" });
|
|
88545
88781
|
} catch {
|
|
88546
88782
|
try {
|
|
88547
|
-
|
|
88783
|
+
execSync10(`xdg-open "${background.dashboard}"`, { stdio: "pipe" });
|
|
88548
88784
|
} catch {
|
|
88549
88785
|
}
|
|
88550
88786
|
}
|
|
@@ -88554,7 +88790,7 @@ ${hookScript}`, "utf-8");
|
|
|
88554
88790
|
break;
|
|
88555
88791
|
case "1":
|
|
88556
88792
|
try {
|
|
88557
|
-
|
|
88793
|
+
execSync10("memorix background restart", { stdio: "pipe", timeout: 15e3 });
|
|
88558
88794
|
setStatusMsg({ text: "Restarted.", type: "success" });
|
|
88559
88795
|
} catch (e3) {
|
|
88560
88796
|
setStatusMsg({ text: `Restart failed: ${e3}`, type: "error" });
|
|
@@ -88562,7 +88798,7 @@ ${hookScript}`, "utf-8");
|
|
|
88562
88798
|
break;
|
|
88563
88799
|
case "2":
|
|
88564
88800
|
try {
|
|
88565
|
-
|
|
88801
|
+
execSync10("memorix background stop", { stdio: "pipe", timeout: 1e4 });
|
|
88566
88802
|
setStatusMsg({ text: "Stopped.", type: "success" });
|
|
88567
88803
|
} catch (e3) {
|
|
88568
88804
|
setStatusMsg({ text: `Stop failed: ${e3}`, type: "error" });
|
|
@@ -88576,7 +88812,7 @@ ${hookScript}`, "utf-8");
|
|
|
88576
88812
|
switch (action) {
|
|
88577
88813
|
case "1":
|
|
88578
88814
|
try {
|
|
88579
|
-
|
|
88815
|
+
execSync10("memorix background start", { stdio: "pipe", timeout: 15e3 });
|
|
88580
88816
|
setStatusMsg({ text: "Started.", type: "success" });
|
|
88581
88817
|
} catch (e3) {
|
|
88582
88818
|
setStatusMsg({ text: `Start failed: ${e3}`, type: "error" });
|
|
@@ -88595,17 +88831,17 @@ ${hookScript}`, "utf-8");
|
|
|
88595
88831
|
const handleDashboardAction = useCallback5(async (action) => {
|
|
88596
88832
|
setStatusMsg(null);
|
|
88597
88833
|
try {
|
|
88598
|
-
const { execSync:
|
|
88834
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
88599
88835
|
if (background.healthy && background.dashboard) {
|
|
88600
88836
|
if (action === "1") {
|
|
88601
88837
|
try {
|
|
88602
|
-
|
|
88838
|
+
execSync10(`start "" "${background.dashboard}"`, { stdio: "pipe" });
|
|
88603
88839
|
} catch {
|
|
88604
88840
|
try {
|
|
88605
|
-
|
|
88841
|
+
execSync10(`open "${background.dashboard}"`, { stdio: "pipe" });
|
|
88606
88842
|
} catch {
|
|
88607
88843
|
try {
|
|
88608
|
-
|
|
88844
|
+
execSync10(`xdg-open "${background.dashboard}"`, { stdio: "pipe" });
|
|
88609
88845
|
} catch {
|
|
88610
88846
|
}
|
|
88611
88847
|
}
|
|
@@ -88617,7 +88853,7 @@ ${hookScript}`, "utf-8");
|
|
|
88617
88853
|
} else {
|
|
88618
88854
|
if (action === "1") {
|
|
88619
88855
|
try {
|
|
88620
|
-
|
|
88856
|
+
execSync10("memorix background start", { stdio: "pipe", timeout: 15e3 });
|
|
88621
88857
|
setStatusMsg({ text: "Started.", type: "success" });
|
|
88622
88858
|
setBackground(await getBackgroundStatus());
|
|
88623
88859
|
} catch (e3) {
|