kirograph 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/commands/attack-surface.js +3 -1
  3. package/dist/bin/commands/attack-surface.js.map +2 -2
  4. package/dist/bin/commands/help.js +1 -1
  5. package/dist/bin/commands/help.js.map +2 -2
  6. package/dist/bin/commands/memory.js +4 -4
  7. package/dist/bin/commands/memory.js.map +2 -2
  8. package/dist/bin/commands/security-export.js +3 -1
  9. package/dist/bin/commands/security-export.js.map +2 -2
  10. package/dist/bin/commands/wiki.js +2 -0
  11. package/dist/bin/commands/wiki.js.map +2 -2
  12. package/dist/bin/installer/config-prompt.js +13 -9
  13. package/dist/bin/installer/config-prompt.js.map +2 -2
  14. package/dist/bin/installer/index.js +34 -8
  15. package/dist/bin/installer/index.js.map +2 -2
  16. package/dist/bin/kirograph.js +1 -1
  17. package/dist/config.js +15 -5
  18. package/dist/config.js.map +2 -2
  19. package/dist/jev/client.js.map +2 -2
  20. package/dist/jev/factory.js +36 -0
  21. package/dist/jev/factory.js.map +7 -0
  22. package/dist/jev/strands-client.js +89 -0
  23. package/dist/jev/strands-client.js.map +7 -0
  24. package/dist/jev/types.js.map +1 -1
  25. package/dist/mcp/handlers/memory.js +4 -3
  26. package/dist/mcp/handlers/memory.js.map +2 -2
  27. package/dist/mcp/handlers/security.js +3 -1
  28. package/dist/mcp/handlers/security.js.map +2 -2
  29. package/dist/mcp/handlers/wiki.js +2 -0
  30. package/dist/mcp/handlers/wiki.js.map +2 -2
  31. package/dist/memory/index.js +6 -4
  32. package/dist/memory/index.js.map +2 -2
  33. package/dist/memory/relation-jev.js.map +1 -1
  34. package/dist/security/attack-surface.js +6 -6
  35. package/dist/security/attack-surface.js.map +2 -2
  36. package/dist/security/auth-detection-jev.js.map +1 -1
  37. package/dist/wiki/contradiction-jev.js.map +1 -1
  38. package/dist/wiki/index.js +12 -6
  39. package/dist/wiki/index.js.map +2 -2
  40. package/dist/wiki/lint.js +3 -3
  41. package/dist/wiki/lint.js.map +2 -2
  42. package/package.json +1 -1
package/dist/wiki/lint.js CHANGED
@@ -78,15 +78,15 @@ async function lintWiki(wikiDb, opts = {}) {
78
78
  (i) => i.kind === "contradiction" && i.detail.includes(other.slug)
79
79
  );
80
80
  if (alreadyReported) continue;
81
- if (opts.contradictionMode === "jev" && opts.jevClient) {
81
+ if ((opts.contradictionMode === "jev" || opts.contradictionMode === "strands") && opts.decisionClient) {
82
82
  const { checkContradictionWithJev } = await Promise.resolve().then(() => require("./contradiction-jev.js"));
83
- const result = await checkContradictionWithJev(opts.jevClient, page.content, other.content);
83
+ const result = await checkContradictionWithJev(opts.decisionClient, page.content, other.content);
84
84
  const threshold = opts.contradictionConfidenceThreshold ?? 0.7;
85
85
  if (result.contradicts && result.confidence >= threshold) {
86
86
  issues.push({
87
87
  kind: "contradiction",
88
88
  slug: page.slug,
89
- detail: `Possible contradiction with [[${other.slug}]] \u2014 jev confidence: ${result.confidence.toFixed(2)}`,
89
+ detail: `Possible contradiction with [[${other.slug}]] \u2014 ${opts.contradictionMode} confidence: ${result.confidence.toFixed(2)}`,
90
90
  relatedSlug: other.slug
91
91
  });
92
92
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/wiki/lint.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph Wiki \u2014 Lint\n *\n * Health checks: contradictions (FTS similarity), orphan pages,\n * broken [[slug]] cross-references.\n */\n\nimport * as path from 'path';\nimport type { WikiLintIssue } from './types';\nimport type { WikiDatabase } from './database';\nimport type { JevClient } from '../jev/client';\nimport { extractLinks } from './links';\nimport { parseFrontmatter, validatePageSchema } from './typed-pages';\n\nexport interface LintWikiOptions {\n /** 'heuristic' (default): keyword co-occurrence. 'jev': ask jev to judge each FTS-similar pair. */\n contradictionMode?: 'heuristic' | 'jev';\n /** Confidence (0.0\u20131.0) above which a jev contradiction judgment is reported. Default: 0.7. */\n contradictionConfidenceThreshold?: number;\n /** Required when contradictionMode is 'jev'. */\n jevClient?: JevClient;\n /**\n * When set, pages declaring `_type` in their frontmatter are validated\n * against `.kirograph/wiki-schemas/<type>.schema.json` (wikiTypedPages).\n */\n wikiSchemasDir?: string;\n}\n\nexport async function lintWiki(wikiDb: WikiDatabase, opts: LintWikiOptions = {}): Promise<WikiLintIssue[]> {\n const issues: WikiLintIssue[] = [];\n const pages = wikiDb.listPages();\n const slugSet = new Set(pages.map(p => p.slug));\n\n for (const page of pages) {\n // Typed-page schema validation (opt-in via wikiTypedPages)\n if (opts.wikiSchemasDir) {\n const { type, fields } = parseFrontmatter(page.content);\n if (type) {\n for (const violation of validatePageSchema(fields, type, opts.wikiSchemasDir)) {\n issues.push({\n kind: 'schema_error',\n slug: page.slug,\n detail: `[${type}] ${violation}`,\n });\n }\n }\n }\n\n // Broken [[slug]] links\n for (const linked of extractLinks(page.content)) {\n if (!slugSet.has(linked)) {\n issues.push({\n kind: 'broken_link',\n slug: page.slug,\n detail: `Broken link to [[${linked}]] \u2014 page does not exist`,\n relatedSlug: linked,\n });\n }\n }\n\n // Orphan: no ## Related section and no incoming links from other pages\n const hasRelated = /^## Related/m.test(page.content);\n const hasIncoming = pages.some(p => p.slug !== page.slug && extractLinks(p.content).includes(page.slug));\n if (!hasRelated && !hasIncoming && pages.length > 1) {\n issues.push({\n kind: 'orphan',\n slug: page.slug,\n detail: 'Page has no ## Related section and no incoming links from other pages',\n });\n }\n\n // Stale: ## Sources section present but no date found (can't verify freshness)\n const sourcesMatch = page.content.match(/## Sources\\n([\\s\\S]*?)(?=\\n## |\\n*$)/);\n if (sourcesMatch) {\n const sourcesBlock = sourcesMatch[1];\n const hasDates = /\\d{4}-\\d{2}-\\d{2}/.test(sourcesBlock);\n if (!hasDates) {\n issues.push({\n kind: 'stale',\n slug: page.slug,\n detail: '## Sources section has no dates \u2014 cannot verify freshness',\n });\n }\n }\n\n // Contradictions: FTS similarity with other pages on the same topic\n const similar = wikiDb.search(page.title, 5);\n for (const { page: other } of similar) {\n if (other.slug === page.slug) continue;\n const alreadyReported = issues.some(\n i => i.kind === 'contradiction' && i.detail.includes(other.slug)\n );\n if (alreadyReported) continue;\n\n if (opts.contradictionMode === 'jev' && opts.jevClient) {\n const { checkContradictionWithJev } = await Promise.resolve().then(() => require('./contradiction-jev.js'));\n const result = await checkContradictionWithJev(opts.jevClient, page.content, other.content);\n const threshold = opts.contradictionConfidenceThreshold ?? 0.7;\n if (result.contradicts && result.confidence >= threshold) {\n issues.push({\n kind: 'contradiction',\n slug: page.slug,\n detail: `Possible contradiction with [[${other.slug}]] \u2014 jev confidence: ${result.confidence.toFixed(2)}`,\n relatedSlug: other.slug,\n });\n }\n continue;\n }\n\n // Heuristic (default): co-occurring negation keywords on both pages\n const contradictionSignals = ['instead of', 'not', 'replaced by', 'superseded', 'deprecated'];\n const bothMentionSignal = contradictionSignals.some(\n sig => page.content.toLowerCase().includes(sig) && other.content.toLowerCase().includes(sig)\n );\n if (bothMentionSignal) {\n issues.push({\n kind: 'contradiction',\n slug: page.slug,\n detail: `Possible contradiction with [[${other.slug}]] \u2014 both pages contain negation signals on shared topics`,\n relatedSlug: other.slug,\n });\n }\n }\n }\n\n return issues;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA,mBAA6B;AAC7B,yBAAqD;AAgBrD,eAAsB,SAAS,QAAsB,OAAwB,CAAC,GAA6B;AACzG,QAAM,SAA0B,CAAC;AACjC,QAAM,QAAQ,OAAO,UAAU;AAC/B,QAAM,UAAU,IAAI,IAAI,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC;AAE9C,aAAW,QAAQ,OAAO;AAExB,QAAI,KAAK,gBAAgB;AACvB,YAAM,EAAE,MAAM,OAAO,QAAI,qCAAiB,KAAK,OAAO;AACtD,UAAI,MAAM;AACR,mBAAW,iBAAa,uCAAmB,QAAQ,MAAM,KAAK,cAAc,GAAG;AAC7E,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,YACX,QAAQ,IAAI,IAAI,KAAK,SAAS;AAAA,UAChC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,eAAW,cAAU,2BAAa,KAAK,OAAO,GAAG;AAC/C,UAAI,CAAC,QAAQ,IAAI,MAAM,GAAG;AACxB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,UACX,QAAQ,oBAAoB,MAAM;AAAA,UAClC,aAAa;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,aAAa,eAAe,KAAK,KAAK,OAAO;AACnD,UAAM,cAAc,MAAM,KAAK,OAAK,EAAE,SAAS,KAAK,YAAQ,2BAAa,EAAE,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;AACvG,QAAI,CAAC,cAAc,CAAC,eAAe,MAAM,SAAS,GAAG;AACnD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,QACX,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAGA,UAAM,eAAe,KAAK,QAAQ,MAAM,sCAAsC;AAC9E,QAAI,cAAc;AAChB,YAAM,eAAe,aAAa,CAAC;AACnC,YAAM,WAAW,oBAAoB,KAAK,YAAY;AACtD,UAAI,CAAC,UAAU;AACb,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,UACX,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAGA,UAAM,UAAU,OAAO,OAAO,KAAK,OAAO,CAAC;AAC3C,eAAW,EAAE,MAAM,MAAM,KAAK,SAAS;AACrC,UAAI,MAAM,SAAS,KAAK,KAAM;AAC9B,YAAM,kBAAkB,OAAO;AAAA,QAC7B,OAAK,EAAE,SAAS,mBAAmB,EAAE,OAAO,SAAS,MAAM,IAAI;AAAA,MACjE;AACA,UAAI,gBAAiB;AAErB,UAAI,KAAK,sBAAsB,SAAS,KAAK,WAAW;AACtD,cAAM,EAAE,0BAA0B,IAAI,MAAM,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,wBAAwB,CAAC;AAC1G,cAAM,SAAS,MAAM,0BAA0B,KAAK,WAAW,KAAK,SAAS,MAAM,OAAO;AAC1F,cAAM,YAAY,KAAK,oCAAoC;AAC3D,YAAI,OAAO,eAAe,OAAO,cAAc,WAAW;AACxD,iBAAO,KAAK;AAAA,YACV,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,YACX,QAAQ,iCAAiC,MAAM,IAAI,6BAAwB,OAAO,WAAW,QAAQ,CAAC,CAAC;AAAA,YACvG,aAAa,MAAM;AAAA,UACrB,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAGA,YAAM,uBAAuB,CAAC,cAAc,OAAO,eAAe,cAAc,YAAY;AAC5F,YAAM,oBAAoB,qBAAqB;AAAA,QAC7C,SAAO,KAAK,QAAQ,YAAY,EAAE,SAAS,GAAG,KAAK,MAAM,QAAQ,YAAY,EAAE,SAAS,GAAG;AAAA,MAC7F;AACA,UAAI,mBAAmB;AACrB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,UACX,QAAQ,iCAAiC,MAAM,IAAI;AAAA,UACnD,aAAa,MAAM;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["/**\n * KiroGraph Wiki \u2014 Lint\n *\n * Health checks: contradictions (FTS similarity), orphan pages,\n * broken [[slug]] cross-references.\n */\n\nimport * as path from 'path';\nimport type { WikiLintIssue } from './types';\nimport type { WikiDatabase } from './database';\nimport type { DecisionClient } from '../jev/types';\nimport { extractLinks } from './links';\nimport { parseFrontmatter, validatePageSchema } from './typed-pages';\n\nexport interface LintWikiOptions {\n /** 'heuristic' (default): keyword co-occurrence. 'jev'/'strands': ask the model to judge each FTS-similar pair. */\n contradictionMode?: 'heuristic' | 'jev' | 'strands';\n /** Confidence (0.0\u20131.0) above which a model contradiction judgment is reported. Default: 0.7. */\n contradictionConfidenceThreshold?: number;\n /** Required when contradictionMode is 'jev' or 'strands'. */\n decisionClient?: DecisionClient;\n /**\n * When set, pages declaring `_type` in their frontmatter are validated\n * against `.kirograph/wiki-schemas/<type>.schema.json` (wikiTypedPages).\n */\n wikiSchemasDir?: string;\n}\n\nexport async function lintWiki(wikiDb: WikiDatabase, opts: LintWikiOptions = {}): Promise<WikiLintIssue[]> {\n const issues: WikiLintIssue[] = [];\n const pages = wikiDb.listPages();\n const slugSet = new Set(pages.map(p => p.slug));\n\n for (const page of pages) {\n // Typed-page schema validation (opt-in via wikiTypedPages)\n if (opts.wikiSchemasDir) {\n const { type, fields } = parseFrontmatter(page.content);\n if (type) {\n for (const violation of validatePageSchema(fields, type, opts.wikiSchemasDir)) {\n issues.push({\n kind: 'schema_error',\n slug: page.slug,\n detail: `[${type}] ${violation}`,\n });\n }\n }\n }\n\n // Broken [[slug]] links\n for (const linked of extractLinks(page.content)) {\n if (!slugSet.has(linked)) {\n issues.push({\n kind: 'broken_link',\n slug: page.slug,\n detail: `Broken link to [[${linked}]] \u2014 page does not exist`,\n relatedSlug: linked,\n });\n }\n }\n\n // Orphan: no ## Related section and no incoming links from other pages\n const hasRelated = /^## Related/m.test(page.content);\n const hasIncoming = pages.some(p => p.slug !== page.slug && extractLinks(p.content).includes(page.slug));\n if (!hasRelated && !hasIncoming && pages.length > 1) {\n issues.push({\n kind: 'orphan',\n slug: page.slug,\n detail: 'Page has no ## Related section and no incoming links from other pages',\n });\n }\n\n // Stale: ## Sources section present but no date found (can't verify freshness)\n const sourcesMatch = page.content.match(/## Sources\\n([\\s\\S]*?)(?=\\n## |\\n*$)/);\n if (sourcesMatch) {\n const sourcesBlock = sourcesMatch[1];\n const hasDates = /\\d{4}-\\d{2}-\\d{2}/.test(sourcesBlock);\n if (!hasDates) {\n issues.push({\n kind: 'stale',\n slug: page.slug,\n detail: '## Sources section has no dates \u2014 cannot verify freshness',\n });\n }\n }\n\n // Contradictions: FTS similarity with other pages on the same topic\n const similar = wikiDb.search(page.title, 5);\n for (const { page: other } of similar) {\n if (other.slug === page.slug) continue;\n const alreadyReported = issues.some(\n i => i.kind === 'contradiction' && i.detail.includes(other.slug)\n );\n if (alreadyReported) continue;\n\n if ((opts.contradictionMode === 'jev' || opts.contradictionMode === 'strands') && opts.decisionClient) {\n const { checkContradictionWithJev } = await Promise.resolve().then(() => require('./contradiction-jev.js'));\n const result = await checkContradictionWithJev(opts.decisionClient, page.content, other.content);\n const threshold = opts.contradictionConfidenceThreshold ?? 0.7;\n if (result.contradicts && result.confidence >= threshold) {\n issues.push({\n kind: 'contradiction',\n slug: page.slug,\n detail: `Possible contradiction with [[${other.slug}]] \u2014 ${opts.contradictionMode} confidence: ${result.confidence.toFixed(2)}`,\n relatedSlug: other.slug,\n });\n }\n continue;\n }\n\n // Heuristic (default): co-occurring negation keywords on both pages\n const contradictionSignals = ['instead of', 'not', 'replaced by', 'superseded', 'deprecated'];\n const bothMentionSignal = contradictionSignals.some(\n sig => page.content.toLowerCase().includes(sig) && other.content.toLowerCase().includes(sig)\n );\n if (bothMentionSignal) {\n issues.push({\n kind: 'contradiction',\n slug: page.slug,\n detail: `Possible contradiction with [[${other.slug}]] \u2014 both pages contain negation signals on shared topics`,\n relatedSlug: other.slug,\n });\n }\n }\n }\n\n return issues;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kirograph",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Semantic code knowledge graph for Kiro: fewer tool calls, instant symbol lookups, 100% local.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",