knodin 0.7.5 → 0.8.2

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 (75) hide show
  1. package/README.md +18 -3
  2. package/benchmarks/competitors/SYNTHESIS.md +66 -0
  3. package/dist/bin/cli.js +371 -66
  4. package/dist/bin/launcher.js +16 -1
  5. package/dist/src/agent-integration.js +82 -16
  6. package/dist/src/artifact-refresh.js +2 -1
  7. package/dist/src/cli-args.js +19 -1
  8. package/dist/src/cli-model.js +28 -2
  9. package/dist/src/codeflow-replay.js +2 -1
  10. package/dist/src/compare.js +39 -0
  11. package/dist/src/competitive-constraints.js +2 -1
  12. package/dist/src/competitive-runner.js +4 -4
  13. package/dist/src/context-export.js +3 -2
  14. package/dist/src/context.js +1 -1
  15. package/dist/src/deterministic-random.js +34 -0
  16. package/dist/src/diagnostics-write-helper.js +473 -0
  17. package/dist/src/diagnostics.js +1160 -133
  18. package/dist/src/doctor.js +3 -1
  19. package/dist/src/engine/ann-hnsw.js +2 -12
  20. package/dist/src/engine/file-walker.js +8 -2
  21. package/dist/src/engine/git-history.js +12 -12
  22. package/dist/src/engine/index.js +1174 -313
  23. package/dist/src/engine/sarif-import.js +341 -0
  24. package/dist/src/engine/scip-import.js +28 -13
  25. package/dist/src/engine/source-policy.js +16 -0
  26. package/dist/src/engine/state-paths.js +175 -0
  27. package/dist/src/execution-profile.js +15 -10
  28. package/dist/src/failure-diagnosis.js +7 -1
  29. package/dist/src/graph-layout.js +173 -0
  30. package/dist/src/index-activity.js +2 -1
  31. package/dist/src/init.js +86 -45
  32. package/dist/src/lifecycle-health.js +41 -9
  33. package/dist/src/mcp-graph-worker.js +69 -0
  34. package/dist/src/mcp-reliability.js +154 -0
  35. package/dist/src/mcp-worker-supervisor.js +350 -0
  36. package/dist/src/mirror.js +290 -0
  37. package/dist/src/node-runtime.js +157 -0
  38. package/dist/src/output-compression.js +2 -1
  39. package/dist/src/output-telemetry.js +16 -11
  40. package/dist/src/progressive-evidence.js +30 -26
  41. package/dist/src/pure-compression-cli.js +4 -3
  42. package/dist/src/relationship-adapters.js +15 -8
  43. package/dist/src/release-preflight.js +13 -10
  44. package/dist/src/repair-lease.js +85 -0
  45. package/dist/src/repository-init-process.js +13 -9
  46. package/dist/src/repository-management.js +34 -4
  47. package/dist/src/response-budget.js +8 -6
  48. package/dist/src/server.js +80 -35
  49. package/dist/src/structural-fast-path.js +16 -10
  50. package/dist/src/structural-snapshot.js +6 -2
  51. package/dist/src/system-config.js +25 -2
  52. package/dist/src/tools/knodin-tools.js +142 -31
  53. package/dist/src/update-ceremony.js +9 -5
  54. package/dist/src/update-trust.js +5 -4
  55. package/dist/src/visualization.js +372 -19
  56. package/dist/src/worktree-lifecycle.js +5 -2
  57. package/docs/BEHAVIORAL-CONTRACT.md +72 -0
  58. package/docs/CLI.md +20 -1
  59. package/docs/COMPARISON.md +403 -0
  60. package/docs/COMPETITIVE-LANDSCAPE-2026-08.md +267 -0
  61. package/docs/DIAGNOSTICS.md +46 -11
  62. package/docs/HANDOFF.md +180 -0
  63. package/docs/INSTALLATION.md +21 -2
  64. package/docs/MCP.md +59 -8
  65. package/docs/PT-ACCESS-RECOMMENDATION.md +5 -7
  66. package/docs/REPOSITORIES-AND-WORKTREES.md +18 -6
  67. package/docs/SCIP-IMPORT.md +5 -0
  68. package/docs/TOKEN-OPTIMIZER-SCORECARD.md +79 -0
  69. package/docs/releases/0.5.1.md +4 -4
  70. package/docs/releases/0.8.0.md +74 -0
  71. package/docs/releases/0.8.2.md +34 -0
  72. package/package.json +17 -4
  73. package/roadmap/competitive-roadmap.md +3801 -0
  74. package/schemas/release-attestation-v1.schema.json +1 -1
  75. package/schemas/support-bundle-v2.schema.json +212 -0
@@ -168,7 +168,7 @@ function readAgentConfig(agent, file) {
168
168
  };
169
169
  }
170
170
  const document = JSON.parse(content);
171
- const registration = document.mcpServers?.knodin;
171
+ const registration = document.mcpServers?.knodin ?? document.servers?.knodin;
172
172
  return {
173
173
  agent,
174
174
  file,
@@ -188,6 +188,7 @@ function configuredAgentCommands(repo) {
188
188
  { agent: "claude", file: ".mcp.json" },
189
189
  { agent: "codex", file: ".codex/config.toml" },
190
190
  { agent: "gemini", file: ".gemini/settings.json" },
191
+ { agent: "copilot", file: ".vscode/mcp.json" },
191
192
  { agent: "antigravity", file: ".agents/mcp_config.json" },
192
193
  ];
193
194
  return candidates.map(({ agent, file }) => readAgentConfig(agent, path.join(repo, file)));
@@ -197,6 +198,7 @@ function personalAgentCommands(homeDir) {
197
198
  readAgentConfig("claude", path.join(homeDir, ".claude.json")),
198
199
  readAgentConfig("codex", path.join(homeDir, ".codex", "config.toml")),
199
200
  readAgentConfig("gemini", path.join(homeDir, ".gemini", "settings.json")),
201
+ readAgentConfig("copilot", path.join(homeDir, "Library", "Application Support", "Code", "User", "mcp.json")),
200
202
  readAgentConfig("antigravity", path.join(homeDir, ".agents", "mcp_config.json")),
201
203
  ];
202
204
  }
@@ -44,22 +44,12 @@
44
44
  * degenerate "scan everything" implementation is observable at the integration
45
45
  * layer (the gate test counts these calls and asserts real pruning).
46
46
  */
47
+ import { DEFAULT_PRNG_SEED, mulberry32 } from "../deterministic-random.js";
47
48
  import * as embeddings from "./embeddings.js";
48
49
  const DEFAULT_M = 16;
49
50
  const DEFAULT_EF_CONSTRUCTION = 200;
50
51
  const DEFAULT_EF_SEARCH = 200;
51
- const DEFAULT_SEED = 0x9e3779b9;
52
- /** Deterministic PRNG so index topology (and thus recall) is reproducible. */
53
- function mulberry32(seed) {
54
- let a = seed >>> 0;
55
- return () => {
56
- a |= 0;
57
- a = (a + 0x6d2b79f5) | 0;
58
- let t = Math.imul(a ^ (a >>> 15), 1 | a);
59
- t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
60
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
61
- };
62
- }
52
+ const DEFAULT_SEED = DEFAULT_PRNG_SEED;
63
53
  class Hnsw {
64
54
  nodes = [];
65
55
  entryPoint = -1;
@@ -1,8 +1,14 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { isIndexablePath } from "./prune.js";
4
- function comparePaths(left, right) {
5
- return left < right ? -1 : left > right ? 1 : 0;
4
+ /**
5
+ * Byte-order path comparison. Deliberately NOT `localeCompare`: index order must
6
+ * be identical on every machine, and locale collation is not.
7
+ */
8
+ export function comparePaths(left, right) {
9
+ if (left < right)
10
+ return -1;
11
+ return left > right ? 1 : 0;
6
12
  }
7
13
  /**
8
14
  * Deterministically enumerate regular files beneath a repository without
@@ -1,5 +1,6 @@
1
1
  import childProcess from "node:child_process";
2
2
  import path from "node:path";
3
+ import { compareBytes } from "../compare.js";
3
4
  export const DEFAULT_GIT_HISTORY_BOUNDS = Object.freeze({
4
5
  maxCommits: 250,
5
6
  maxFiles: 25,
@@ -101,7 +102,7 @@ function parseLog(output) {
101
102
  */
102
103
  export function collectGitHistorySignals(repoPath, filePaths, limits = {}) {
103
104
  const bounds = resolveBounds(limits);
104
- const requestedAll = [...new Set(filePaths.map(safeHistoryFile))].sort();
105
+ const requestedAll = [...new Set(filePaths.map(safeHistoryFile))].sort(compareBytes);
105
106
  const requested = requestedAll.slice(0, bounds.maxFiles);
106
107
  const omissions = [];
107
108
  if (requestedAll.length > requested.length) {
@@ -133,13 +134,10 @@ export function collectGitHistorySignals(repoPath, filePaths, limits = {}) {
133
134
  detail: "HEAD does not exist; no historical facts are available",
134
135
  }, requested);
135
136
  }
136
- const availability = reason === "git-unavailable"
137
- ? "git-unavailable"
138
- : reason === "not-a-repository"
139
- ? "not-a-repository"
140
- : reason === "timeout"
141
- ? "timeout"
142
- : "unavailable";
137
+ // A recognised probe failure is reported verbatim; anything else degrades
138
+ // to the generic bucket rather than leaking an unmodelled reason string.
139
+ const recognised = ["git-unavailable", "not-a-repository", "timeout"];
140
+ const availability = recognised.find((known) => known === reason) ?? "unavailable";
143
141
  return emptyResult(availability, bounds, commands, {
144
142
  reason,
145
143
  detail: "Git HEAD probe failed; history signals were omitted",
@@ -232,12 +230,14 @@ export function collectGitHistorySignals(repoPath, filePaths, limits = {}) {
232
230
  file,
233
231
  relatedFile,
234
232
  sharedCommitCount: hashes.size,
235
- commits: [...hashes].sort(),
233
+ commits: [...hashes].sort(compareBytes),
236
234
  };
237
235
  })
236
+ // Byte order: these tie-breaks decide which co-change facts survive the
237
+ // maxRelatedFiles slice below, not merely how the surviving ones read.
238
238
  .sort((a, b) => b.sharedCommitCount - a.sharedCommitCount ||
239
- a.file.localeCompare(b.file) ||
240
- a.relatedFile.localeCompare(b.relatedFile));
239
+ compareBytes(a.file, b.file) ||
240
+ compareBytes(a.relatedFile, b.relatedFile));
241
241
  const coChange = allCoChange.slice(0, bounds.maxRelatedFiles);
242
242
  if (coChange.length < allCoChange.length) {
243
243
  omissions.push({
@@ -246,7 +246,7 @@ export function collectGitHistorySignals(repoPath, filePaths, limits = {}) {
246
246
  });
247
247
  }
248
248
  const churn = requested.map((file) => {
249
- const hashes = [...(commitsByFile.get(file) ?? [])].sort();
249
+ const hashes = [...(commitsByFile.get(file) ?? [])].sort(compareBytes);
250
250
  return { file, commitCount: hashes.length, commits: hashes };
251
251
  });
252
252
  const coupling = coChange.map((fact) => {