skillwiki 0.10.80 → 0.10.81

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.
@@ -6285,7 +6285,7 @@ async function runQuery(input) {
6285
6285
  const sources = Array.isArray(fm.data.sources) ? fm.data.sources.map(String) : [];
6286
6286
  const split = splitFrontmatter(text);
6287
6287
  const body = split.ok ? split.data.body : text;
6288
- const keywordScore = computeKeywordScore(queryTerms, title, tags, body);
6288
+ const keywordScore = computeKeywordScore(queryTerms, title, tags, body, p.relPath);
6289
6289
  pages.push({
6290
6290
  relPath: p.relPath,
6291
6291
  title,
@@ -6296,38 +6296,21 @@ async function runQuery(input) {
6296
6296
  historicalCycle: isHistoricalCyclePage(p.relPath, title)
6297
6297
  });
6298
6298
  }
6299
- const seedPaths = /* @__PURE__ */ new Set();
6300
- const operationalSeedPaths = /* @__PURE__ */ new Set();
6301
- let historicalCyclePageCount = 0;
6302
- let hasDirectOperationalSeed = false;
6303
- for (const page of pages) {
6304
- if (page.historicalCycle) historicalCyclePageCount += 1;
6305
- if (page.keywordScore <= 0) continue;
6306
- seedPaths.add(page.relPath);
6307
- if (!page.historicalCycle) {
6308
- operationalSeedPaths.add(page.relPath);
6309
- hasDirectOperationalSeed = true;
6310
- }
6299
+ let structural;
6300
+ let results;
6301
+ let rankingGuardrails;
6302
+ if (scope === "all") {
6303
+ const rankedWork = rankPages(pages.filter((page) => isWorkPath(page.relPath)), graph, queryTerms);
6304
+ const rankedTyped = rankPages(pages.filter((page) => !isWorkPath(page.relPath)), graph, queryTerms);
6305
+ structural = [...rankedWork.results, ...rankedTyped.results];
6306
+ results = zipMergeScopeResults(rankedWork.results, rankedTyped.results, limit);
6307
+ rankingGuardrails = rankedTyped.rankingGuardrails;
6308
+ } else {
6309
+ const ranked = rankPages(pages, graph, queryTerms);
6310
+ structural = ranked.results;
6311
+ results = structural.slice(0, limit);
6312
+ rankingGuardrails = ranked.rankingGuardrails;
6311
6313
  }
6312
- const suppressRepetitiveHistoricalCycles = historicalCyclePageCount >= 3 && hasDirectOperationalSeed;
6313
- const structuralSeedPaths = suppressRepetitiveHistoricalCycles ? operationalSeedPaths : seedPaths;
6314
- const structural = pages.map((page) => {
6315
- const sourceOverlap = scoreSourceOverlap(page, pages, structuralSeedPaths);
6316
- const wikilink = scoreWikilink(page.relPath, structuralSeedPaths, graph);
6317
- const aa = scoreAdamicAdar(page.relPath, structuralSeedPaths, graph);
6318
- const typeAffinity = scoreTypeAffinity(page.type, queryTerms);
6319
- const isSeed = page.keywordScore > 0;
6320
- const structuralBoost = sourceOverlap * W_SOURCE_OVERLAP + wikilink * W_WIKILINK + aa * W_ADAMIC_ADAR;
6321
- const composite = isSeed ? page.keywordScore * W_KEYWORD + structuralBoost + typeAffinity * W_TYPE_AFFINITY : structuralBoost * NON_SEED_FACTOR + typeAffinity * W_TYPE_AFFINITY;
6322
- const guardedComposite = suppressRepetitiveHistoricalCycles && page.historicalCycle ? composite * HISTORICAL_CYCLE_FACTOR : composite;
6323
- return {
6324
- path: page.relPath,
6325
- score: Math.round(guardedComposite * 1e3) / 1e3,
6326
- title: page.title,
6327
- type: page.type
6328
- };
6329
- }).filter((r) => r.score > 0).sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
6330
- let results = structural.slice(0, limit);
6331
6314
  let hybridMeta;
6332
6315
  if (input.hybrid) {
6333
6316
  const index = await loadVectorIndex(input.vault);
@@ -6359,10 +6342,6 @@ async function runQuery(input) {
6359
6342
  }
6360
6343
  const humanHint = results.length === 0 ? pendingSources && pendingSources.length > 0 ? `no matching typed pages found
6361
6344
  ${pendingSources.length} matching pending source(s)` : "no matching pages found" : results.map((r) => `${r.path} (score: ${r.score})`).join("\n");
6362
- const rankingGuardrails = suppressRepetitiveHistoricalCycles ? {
6363
- repetitive_historical_cycles_suppressed: true,
6364
- historical_cycle_page_count: historicalCyclePageCount
6365
- } : void 0;
6366
6345
  return {
6367
6346
  exitCode: ExitCode.OK,
6368
6347
  result: ok({
@@ -6379,6 +6358,92 @@ function queryCandidates(typedKnowledge, workItems, scope) {
6379
6358
  if (scope === "all") return [...typedKnowledge, ...workItems];
6380
6359
  return typedKnowledge;
6381
6360
  }
6361
+ function isWorkPath(relPath) {
6362
+ return relPath.includes("/work/");
6363
+ }
6364
+ var GENERIC_PATH_TERMS = /* @__PURE__ */ new Set([
6365
+ "work",
6366
+ "open",
6367
+ "projects",
6368
+ "spec",
6369
+ "plan",
6370
+ "log",
6371
+ "md",
6372
+ "http",
6373
+ "mcp",
6374
+ "and",
6375
+ "the",
6376
+ "for",
6377
+ "with",
6378
+ "from",
6379
+ "item",
6380
+ "items"
6381
+ ]);
6382
+ function pathSegmentBonus(terms, relPath) {
6383
+ if (!isWorkPath(relPath)) return 0;
6384
+ const segments = new Set(
6385
+ relPath.toLowerCase().split("/").flatMap((part) => {
6386
+ const noExt = part.replace(/\.(md|markdown)$/i, "");
6387
+ return noExt === part ? [part] : [part, noExt];
6388
+ })
6389
+ );
6390
+ let bonus = 0;
6391
+ for (const term of terms) {
6392
+ if (GENERIC_PATH_TERMS.has(term)) continue;
6393
+ if (segments.has(term)) bonus += 100;
6394
+ }
6395
+ return bonus;
6396
+ }
6397
+ function zipMergeScopeResults(work, typed, limit) {
6398
+ const merged = [];
6399
+ const n = Math.max(work.length, typed.length);
6400
+ for (let i = 0; i < n && merged.length < limit; i++) {
6401
+ if (i < work.length) merged.push(work[i]);
6402
+ if (merged.length >= limit) break;
6403
+ if (i < typed.length) merged.push(typed[i]);
6404
+ }
6405
+ return merged;
6406
+ }
6407
+ function rankPages(pages, graph, queryTerms) {
6408
+ const seedPaths = /* @__PURE__ */ new Set();
6409
+ const operationalSeedPaths = /* @__PURE__ */ new Set();
6410
+ let historicalCyclePageCount = 0;
6411
+ let hasDirectOperationalSeed = false;
6412
+ for (const page of pages) {
6413
+ if (page.historicalCycle) historicalCyclePageCount += 1;
6414
+ if (page.keywordScore <= 0) continue;
6415
+ seedPaths.add(page.relPath);
6416
+ if (!page.historicalCycle) {
6417
+ operationalSeedPaths.add(page.relPath);
6418
+ hasDirectOperationalSeed = true;
6419
+ }
6420
+ }
6421
+ const suppressRepetitiveHistoricalCycles = historicalCyclePageCount >= 3 && hasDirectOperationalSeed;
6422
+ const structuralSeedPaths = suppressRepetitiveHistoricalCycles ? operationalSeedPaths : seedPaths;
6423
+ const results = pages.map((page) => {
6424
+ const sourceOverlap = scoreSourceOverlap(page, pages, structuralSeedPaths);
6425
+ const wikilink = scoreWikilink(page.relPath, structuralSeedPaths, graph);
6426
+ const aa = scoreAdamicAdar(page.relPath, structuralSeedPaths, graph);
6427
+ const typeAffinity = scoreTypeAffinity(page.type, queryTerms);
6428
+ const isSeed = page.keywordScore > 0;
6429
+ const structuralBoost = sourceOverlap * W_SOURCE_OVERLAP + wikilink * W_WIKILINK + aa * W_ADAMIC_ADAR;
6430
+ const composite = isSeed ? page.keywordScore * W_KEYWORD + structuralBoost + typeAffinity * W_TYPE_AFFINITY : structuralBoost * NON_SEED_FACTOR + typeAffinity * W_TYPE_AFFINITY;
6431
+ const guardedComposite = suppressRepetitiveHistoricalCycles && page.historicalCycle ? composite * HISTORICAL_CYCLE_FACTOR : composite;
6432
+ return {
6433
+ path: page.relPath,
6434
+ score: Math.round(guardedComposite * 1e3) / 1e3,
6435
+ title: page.title,
6436
+ type: page.type
6437
+ };
6438
+ }).filter((r) => r.score > 0).sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
6439
+ return {
6440
+ results,
6441
+ rankingGuardrails: suppressRepetitiveHistoricalCycles ? {
6442
+ repetitive_historical_cycles_suppressed: true,
6443
+ historical_cycle_page_count: historicalCyclePageCount
6444
+ } : void 0
6445
+ };
6446
+ }
6382
6447
  function scoreSourceOverlap(page, allPages, seedPaths) {
6383
6448
  if (page.sources.length === 0) return 0;
6384
6449
  let total = 0;
@@ -6421,7 +6486,7 @@ function isHistoricalCyclePage(relPath, title) {
6421
6486
  function tokenize2(text) {
6422
6487
  return text.toLowerCase().split(/\s+/).filter((t) => t.length > 0);
6423
6488
  }
6424
- function computeKeywordScore(terms, title, tags, body) {
6489
+ function computeKeywordScore(terms, title, tags, body, relPath) {
6425
6490
  const lowerTitle = title.toLowerCase();
6426
6491
  const lowerTags = tags.map((t) => t.toLowerCase());
6427
6492
  const lowerBody = body.toLowerCase();
@@ -6431,6 +6496,7 @@ function computeKeywordScore(terms, title, tags, body) {
6431
6496
  if (lowerTags.some((t) => t.includes(term))) score += 2;
6432
6497
  if (lowerBody.includes(term)) score += 1;
6433
6498
  }
6499
+ if (relPath) score += pathSegmentBonus(terms, relPath);
6434
6500
  return score;
6435
6501
  }
6436
6502
  async function loadOrBuildGraph(vault) {
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ import {
50
50
  snapshotterHealthChecks,
51
51
  upsertIndexEntry,
52
52
  vectorIndexStatus
53
- } from "./chunk-NX3PJ3NK.js";
53
+ } from "./chunk-G7I34RQW.js";
54
54
  import {
55
55
  normalizeDistTag,
56
56
  readCache,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runSkillwikiMcpStdio
4
- } from "./chunk-NX3PJ3NK.js";
4
+ } from "./chunk-G7I34RQW.js";
5
5
  import "./chunk-7I2TPIV5.js";
6
6
  import "./chunk-KFEOMMWK.js";
7
7
  import "./chunk-GPUK2IAW.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.10.80",
3
+ "version": "0.10.81",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "skillwiki": "dist/cli.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.10.80",
3
+ "version": "0.10.81",
4
4
  "skills": "./",
5
5
  "description": "Project-aware Karpathy-style knowledge base for Claude Code: 21 prompt-only skills (wiki-*, proj-*, using-skillwiki, skillwiki-mcp) backed by the deterministic `skillwiki` CLI.",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.10.80",
3
+ "version": "0.10.81",
4
4
  "description": "Project-aware Karpathy-style knowledge base for Codex with 21 prompt-only skills backed by the deterministic skillwiki CLI.",
5
5
  "author": {
6
6
  "name": "karlorz",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.10.80",
3
+ "version": "0.10.81",
4
4
  "description": "Project-aware Karpathy-style knowledge base: 21 prompt-only skills (wiki-*, proj-*, using-skillwiki, skillwiki-mcp) backed by HTTP MCP wiki_capture.",
5
5
  "author": {
6
6
  "name": "karlorz"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.10.80",
3
+ "version": "0.10.81",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",