@reposkein/mcp 0.3.0 → 0.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.
- package/README.md +73 -1
- package/binary-digests.json +4 -4
- package/dist/SKILL.md +19 -0
- package/dist/cli/agentAdapters.d.ts +68 -0
- package/dist/cli/agentAdapters.js +223 -0
- package/dist/cli/agentAdapters.js.map +1 -0
- package/dist/cli/ansi.d.ts +24 -0
- package/dist/cli/ansi.js +40 -0
- package/dist/cli/ansi.js.map +1 -0
- package/dist/cli/doctor.d.ts +34 -2
- package/dist/cli/doctor.js +51 -6
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/doctorFreshness.d.ts +43 -0
- package/dist/cli/doctorFreshness.js +111 -0
- package/dist/cli/doctorFreshness.js.map +1 -0
- package/dist/cli/doctorSummaries.d.ts +2 -0
- package/dist/cli/doctorSummaries.js +95 -0
- package/dist/cli/doctorSummaries.js.map +1 -0
- package/dist/cli/federatedDiscovery.d.ts +16 -0
- package/dist/cli/federatedDiscovery.js +75 -0
- package/dist/cli/federatedDiscovery.js.map +1 -0
- package/dist/cli/init.d.ts +69 -6
- package/dist/cli/init.js +194 -28
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/sourceSlices.d.ts +17 -0
- package/dist/cli/sourceSlices.js +59 -0
- package/dist/cli/sourceSlices.js.map +1 -0
- package/dist/cli/stats.d.ts +29 -0
- package/dist/cli/stats.js +180 -0
- package/dist/cli/stats.js.map +1 -0
- package/dist/cli/view.d.ts +71 -3
- package/dist/cli/view.js +147 -12
- package/dist/cli/view.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +286 -123
- package/dist/index.js.map +1 -1
- package/dist/indexer/fetchBinary.d.ts +14 -0
- package/dist/indexer/fetchBinary.js +81 -40
- package/dist/indexer/fetchBinary.js.map +1 -1
- package/dist/indexer/runIndexer.d.ts +0 -2
- package/dist/indexer/runIndexer.js +8 -4
- package/dist/indexer/runIndexer.js.map +1 -1
- package/dist/store/JsonlGraphStore.d.ts +13 -3
- package/dist/store/JsonlGraphStore.js +55 -17
- package/dist/store/JsonlGraphStore.js.map +1 -1
- package/dist/store/decisions.d.ts +20 -2
- package/dist/store/decisions.js +35 -2
- package/dist/store/decisions.js.map +1 -1
- package/dist/store/indexedAt.d.ts +18 -0
- package/dist/store/indexedAt.js +56 -0
- package/dist/store/indexedAt.js.map +1 -0
- package/dist/store/instrumentTool.d.ts +40 -0
- package/dist/store/instrumentTool.js +82 -0
- package/dist/store/instrumentTool.js.map +1 -0
- package/dist/store/repoContextCache.d.ts +15 -0
- package/dist/store/repoContextCache.js +26 -0
- package/dist/store/repoContextCache.js.map +1 -0
- package/dist/store/repoSession.d.ts +63 -0
- package/dist/store/repoSession.js +123 -0
- package/dist/store/repoSession.js.map +1 -0
- package/dist/store/resolveRepoPath.d.ts +31 -0
- package/dist/store/resolveRepoPath.js +85 -0
- package/dist/store/resolveRepoPath.js.map +1 -0
- package/dist/store/sessionLog.d.ts +98 -0
- package/dist/store/sessionLog.js +216 -0
- package/dist/store/sessionLog.js.map +1 -0
- package/dist/store/sessionStats.d.ts +55 -0
- package/dist/store/sessionStats.js +140 -0
- package/dist/store/sessionStats.js.map +1 -0
- package/dist/store/sidecar.d.ts +39 -3
- package/dist/store/sidecar.js +89 -5
- package/dist/store/sidecar.js.map +1 -1
- package/dist/store/summaryShards.d.ts +117 -0
- package/dist/store/summaryShards.js +291 -0
- package/dist/store/summaryShards.js.map +1 -0
- package/dist/store/teamConfig.d.ts +13 -0
- package/dist/store/teamConfig.js +49 -0
- package/dist/store/teamConfig.js.map +1 -0
- package/dist/tools/indexerTools.d.ts +14 -2
- package/dist/tools/indexerTools.js +17 -5
- package/dist/tools/indexerTools.js.map +1 -1
- package/dist/tools/recordDecision.js +6 -1
- package/dist/tools/recordDecision.js.map +1 -1
- package/dist/viz/assets/{graph.worker-CC7BeE-8.js → graph.worker-DkH6-lMU.js} +1 -1
- package/dist/viz/assets/index-CxqeGuRS.css +1 -0
- package/dist/viz/assets/index-DiNZyrXx.js +9 -0
- package/dist/viz/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/viz/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/viz/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/dist/viz/assets/r3f-BZY3QR6_.js +336 -0
- package/dist/viz/assets/tanstack-CjXr-L-s.js +62 -0
- package/dist/viz/assets/three-Cpu5RUEM.js +4116 -0
- package/dist/viz/index.html +5 -4
- package/package.json +5 -4
- package/dist/viz/assets/index-C_8UkiJ8.js +0 -9
- package/dist/viz/assets/r3f-Cku1OhB-.js +0 -277
- package/dist/viz/assets/tanstack-DyXcNRWk.js +0 -77
- package/dist/viz/assets/three-Z8XaLGmf.js +0 -3839
package/dist/store/sidecar.js
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { absorbSummaryLines, emptyAccumulator, } from "./summaryShards.js";
|
|
4
|
+
/** Directory holding every agent's sidecar. Git-ignored in full. */
|
|
5
|
+
export function sidecarDir(repoPath) {
|
|
6
|
+
return join(repoPath, ".reposkein", "local");
|
|
7
|
+
}
|
|
8
|
+
/** Filesystem-safe slug for the writing agent.
|
|
9
|
+
*
|
|
10
|
+
* Untrusted input: REPOSKEIN_AGENT comes from whatever launched the server, so
|
|
11
|
+
* it is reduced to `[a-z0-9._-]` and capped. A value that reduces to nothing
|
|
12
|
+
* (or is absent) falls back to "agent", which is also the pre-multi-agent
|
|
13
|
+
* name — so a single-agent setup keeps one stable file. */
|
|
14
|
+
export function agentSlug(agent = process.env.REPOSKEIN_AGENT) {
|
|
15
|
+
const slug = (agent ?? "")
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
18
|
+
.replace(/^[-.]+|[-.]+$/g, "")
|
|
19
|
+
.slice(0, 40)
|
|
20
|
+
.replace(/[-.]+$/, "");
|
|
21
|
+
return slug === "" ? "agent" : slug;
|
|
22
|
+
}
|
|
23
|
+
/** THIS process's sidecar: one file per agent.
|
|
24
|
+
*
|
|
25
|
+
* A single shared `local/summaries.jsonl` meant two agents running against the
|
|
26
|
+
* same checkout silently overwrote each other — `upsertSidecar` rewrites the
|
|
27
|
+
* whole file, so the slower writer's prose vanished with no error anywhere.
|
|
28
|
+
* One file per writer removes the shared mutable state; the indexer folds
|
|
29
|
+
* every `local/summaries*.jsonl` into the committed shards. */
|
|
30
|
+
export function sidecarPath(repoPath, agent) {
|
|
31
|
+
return join(sidecarDir(repoPath), `summaries-${agentSlug(agent)}.jsonl`);
|
|
32
|
+
}
|
|
33
|
+
/** Every agent's sidecar in this repo, sorted, so reads are deterministic and
|
|
34
|
+
* independent of directory order. Includes the pre-split
|
|
35
|
+
* `local/summaries.jsonl` an older client may still be writing. */
|
|
36
|
+
export function sidecarPaths(repoPath) {
|
|
37
|
+
const dir = sidecarDir(repoPath);
|
|
38
|
+
try {
|
|
39
|
+
return readdirSync(dir)
|
|
40
|
+
.filter((f) => f.startsWith("summaries") && f.endsWith(".jsonl"))
|
|
41
|
+
.sort()
|
|
42
|
+
.map((f) => join(dir, f));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
5
47
|
}
|
|
6
48
|
/** Reads the sidecar into a map keyed by node id. Missing file → empty map.
|
|
7
49
|
* Best-effort: malformed lines / read errors are skipped. */
|
|
@@ -38,8 +80,50 @@ export function readSidecar(path) {
|
|
|
38
80
|
}
|
|
39
81
|
return map;
|
|
40
82
|
}
|
|
83
|
+
/** Every agent's sidecar records, folded through the SAME rules the Rust
|
|
84
|
+
* indexer applies — `beats` within the sidecar set, losers preserved — so the
|
|
85
|
+
* server serves exactly the record the next `index` is going to write.
|
|
86
|
+
*
|
|
87
|
+
* This used to be a plain last-file-wins merge, which disagreed with the
|
|
88
|
+
* indexer whenever two agents summarised the same node, and dropped the loser
|
|
89
|
+
* with no trace. Callers should hand `conflicts` to `recordSummaryConflicts`. */
|
|
90
|
+
export function loadAllSidecars(repoPath) {
|
|
91
|
+
const acc = emptyAccumulator();
|
|
92
|
+
for (const p of sidecarPaths(repoPath)) {
|
|
93
|
+
let text;
|
|
94
|
+
try {
|
|
95
|
+
text = readFileSync(p, "utf8");
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
absorbSummaryLines(acc, `local/${basename(p)}`, text);
|
|
101
|
+
}
|
|
102
|
+
return acc;
|
|
103
|
+
}
|
|
104
|
+
/** Convenience view of `loadAllSidecars` for callers that only want the
|
|
105
|
+
* winning record per node id. Divergence losers are dropped on the floor
|
|
106
|
+
* here, so prefer `loadAllSidecars` anywhere they can be recorded. */
|
|
107
|
+
export function readAllSidecars(repoPath) {
|
|
108
|
+
const merged = new Map();
|
|
109
|
+
for (const [id, rec] of loadAllSidecars(repoPath).summaries) {
|
|
110
|
+
const s = (k) => typeof rec.props[k] === "string" ? rec.props[k] : "";
|
|
111
|
+
merged.set(id, {
|
|
112
|
+
id,
|
|
113
|
+
semantic_summary: s("semantic_summary"),
|
|
114
|
+
summary_of_hash: s("summary_of_hash"),
|
|
115
|
+
summary_model: s("summary_model"),
|
|
116
|
+
summary_at: s("summary_at"),
|
|
117
|
+
summary_by: s("summary_by"),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return merged;
|
|
121
|
+
}
|
|
41
122
|
/** Upserts one record and rewrites the sidecar sorted by id (deterministic, no
|
|
42
|
-
* duplicate lines). Creates the local/ dir if needed. Best-effort.
|
|
123
|
+
* duplicate lines). Creates the local/ dir if needed. Best-effort.
|
|
124
|
+
*
|
|
125
|
+
* Rewriting the whole file is safe only because `path` belongs to one agent:
|
|
126
|
+
* see `sidecarPath`. */
|
|
43
127
|
export function upsertSidecar(path, rec) {
|
|
44
128
|
const map = readSidecar(path);
|
|
45
129
|
map.set(rec.id, rec);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar.js","sourceRoot":"","sources":["../../src/store/sidecar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sidecar.js","sourceRoot":"","sources":["../../src/store/sidecar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** Reader for the committed authored summaries, `.reposkein/summaries/<xx>.jsonl`.
|
|
2
|
+
*
|
|
3
|
+
* Sharding replaced a single `.reposkein/summaries.jsonl` for the reason
|
|
4
|
+
* `docs/migrations/2026-08-06-stop-committing-derived-graph.md` records: one
|
|
5
|
+
* committed file that every branch rewrites conflicts on every merge, and no
|
|
6
|
+
* `.gitattributes` rule can fix it, because a forge computes mergeability in a
|
|
7
|
+
* bare repo where tree-level attributes are never consulted. File granularity
|
|
8
|
+
* is the only thing that works there — the same reason decisions are one file
|
|
9
|
+
* each.
|
|
10
|
+
*
|
|
11
|
+
* This module ONLY READS. The Rust indexer is the sole writer of committed
|
|
12
|
+
* shards, so byte-identical output has exactly one serializer to hold to it
|
|
13
|
+
* (serde_json and JSON.stringify differ on escapes and number formatting).
|
|
14
|
+
* Writes from this process go to the git-ignored per-agent sidecar, which the
|
|
15
|
+
* next `index` folds into the shards.
|
|
16
|
+
*
|
|
17
|
+
* Reading never needs a shard key — `readdir` enumerates the files — which is
|
|
18
|
+
* why no BLAKE3 implementation is required on this side.
|
|
19
|
+
*
|
|
20
|
+
* Tolerance is the other half. A shard is a MERGED file: it can carry git
|
|
21
|
+
* conflict markers, duplicate lines from a `merge=union` resolution, or two
|
|
22
|
+
* genuinely different summaries for the same node. None of that may take
|
|
23
|
+
* recall down, and none of it may silently destroy authored prose — the same
|
|
24
|
+
* contract `loadDecisions` keeps for a damaged decision file. */
|
|
25
|
+
export interface SummaryShardRecord {
|
|
26
|
+
id: string;
|
|
27
|
+
/** Every field except `id`, exactly as parsed. */
|
|
28
|
+
props: Record<string, unknown>;
|
|
29
|
+
/** The raw source line, which is also the divergence tiebreak. */
|
|
30
|
+
line: string;
|
|
31
|
+
}
|
|
32
|
+
export interface LoadedSummaryShards {
|
|
33
|
+
/** Winner per node id, insertion-ordered by id. */
|
|
34
|
+
summaries: Map<string, SummaryShardRecord>;
|
|
35
|
+
/** Divergence losers, preserved rather than dropped. */
|
|
36
|
+
conflicts: SummaryShardRecord[];
|
|
37
|
+
warnings: string[];
|
|
38
|
+
/** Set when the pre-sharding `.reposkein/summaries.jsonl` is still present —
|
|
39
|
+
* doctor turns this into "run `reposkein-indexer index` to migrate". */
|
|
40
|
+
legacyFilePresent: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare function summariesDir(repoPath: string): string;
|
|
43
|
+
/** The pre-sharding committed file. Still read (dual-read) for one release. */
|
|
44
|
+
export declare function legacySummariesPath(repoPath: string): string;
|
|
45
|
+
export declare function conflictsPath(repoPath: string): string;
|
|
46
|
+
/** Mirrors the Rust `is_shard_file_name`: exactly two lowercase hex chars. */
|
|
47
|
+
export declare function isShardFileName(name: string): boolean;
|
|
48
|
+
/** A line git left behind from an unresolved textual merge. A canonical
|
|
49
|
+
* summary line always starts with `{`, so a marker run is damage, not data. */
|
|
50
|
+
export declare function isConflictMarker(line: string): boolean;
|
|
51
|
+
/** Whether these props carry an authored summary worth keeping.
|
|
52
|
+
*
|
|
53
|
+
* Deliberately identical to the Rust `has_summary`. The two languages read the
|
|
54
|
+
* same committed shards, so a record one accepts and the other rejects is a
|
|
55
|
+
* divergence between what the server serves and what the indexer writes — and
|
|
56
|
+
* a record with nothing in it must never displace one that has prose, in
|
|
57
|
+
* either language. Pinned by the `null-valued`/`non-string` fixture vectors. */
|
|
58
|
+
export declare function hasSummary(props: Record<string, unknown>): boolean;
|
|
59
|
+
/** Deterministic winner between two records claiming the same node id, when
|
|
60
|
+
* nothing is known about where either came from:
|
|
61
|
+
* newer `summary_at`, then smaller raw line by UTF-8 byte order. Both are
|
|
62
|
+
* pure functions of bytes on disk, so every machine — and the Rust indexer —
|
|
63
|
+
* picks the same winner without coordinating. Kept in lockstep with the Rust
|
|
64
|
+
* `beats` by the shared vectors in `fixtures/summary-shard-vectors.json`.
|
|
65
|
+
*
|
|
66
|
+
* This is the rule for records found in the SAME source (two lines of one
|
|
67
|
+
* merged shard, two agents' sidecars). Across sources of known provenance,
|
|
68
|
+
* use `supersedes`. */
|
|
69
|
+
export declare function beats(candidate: SummaryShardRecord, incumbent: SummaryShardRecord): boolean;
|
|
70
|
+
/** Whether a record from a strictly NEWER-provenance source displaces one
|
|
71
|
+
* already held from an older source.
|
|
72
|
+
*
|
|
73
|
+
* `summary_at` is day-precision (PRD §6.2.5 keeps wall-clock time out of
|
|
74
|
+
* committed bytes), so re-summarising a node already summarised today TIES.
|
|
75
|
+
* Resolving that tie by byte order would silently discard the rewrite. A
|
|
76
|
+
* newer source therefore wins unless it is *strictly older* — which is the
|
|
77
|
+
* case that matters, because that is a stale local record about to clobber a
|
|
78
|
+
* teammate's newer one. Mirrors the Rust `supersedes`. */
|
|
79
|
+
export declare function supersedes(candidate: SummaryShardRecord, incumbent: SummaryShardRecord): boolean;
|
|
80
|
+
export interface SummaryAccumulator {
|
|
81
|
+
summaries: Map<string, SummaryShardRecord>;
|
|
82
|
+
conflicts: SummaryShardRecord[];
|
|
83
|
+
warnings: string[];
|
|
84
|
+
}
|
|
85
|
+
export declare function emptyAccumulator(): SummaryAccumulator;
|
|
86
|
+
/** Folds a whole source of strictly NEWER provenance into `acc`. Mirrors the
|
|
87
|
+
* Rust `absorb_source`: displacement uses `supersedes`, and every displaced
|
|
88
|
+
* record is preserved. */
|
|
89
|
+
export declare function absorbSummarySource(acc: SummaryAccumulator, other: SummaryAccumulator): void;
|
|
90
|
+
/** Folds one file's text in, resolving same-source records with `beats`.
|
|
91
|
+
* Exported for the shared vectors. */
|
|
92
|
+
export declare function absorbSummaryLines(acc: SummaryAccumulator, source: string, text: string): void;
|
|
93
|
+
/** Reads every committed shard plus the pre-sharding file, tolerantly.
|
|
94
|
+
* A missing directory is the normal state for a repo with no authored prose,
|
|
95
|
+
* and returns an empty result rather than an error. */
|
|
96
|
+
export declare function loadSummaryShards(repoPath: string): LoadedSummaryShards;
|
|
97
|
+
/** A cheap fingerprint of everything the summary overlay reads on disk.
|
|
98
|
+
*
|
|
99
|
+
* The store keys its reload on this, so a `git pull` that brings in a
|
|
100
|
+
* teammate's shards — or another agent's sidecar write on this machine — is
|
|
101
|
+
* visible without restarting the process. Stat calls only, O(shards +
|
|
102
|
+
* sidecars), no content read, because this runs on every read and not just on
|
|
103
|
+
* change. mtime alone is not enough on filesystems with coarse timestamps, so
|
|
104
|
+
* size rides along.
|
|
105
|
+
*
|
|
106
|
+
* `sidecarFiles` is injected rather than imported to keep this module free of
|
|
107
|
+
* a cycle with sidecar.ts, which imports the fold from here. */
|
|
108
|
+
export declare function summaryShardsStamp(repoPath: string, sidecarFiles?: (repoPath: string) => string[]): string;
|
|
109
|
+
/** Merges divergence losers into the git-ignored `local/conflicts.jsonl`.
|
|
110
|
+
*
|
|
111
|
+
* Deduped and sorted, so repeated reads converge instead of growing the file,
|
|
112
|
+
* and never truncating: a loser recorded by an earlier run (or by the indexer)
|
|
113
|
+
* stays. Best-effort — failing to record a conflict must not break a tool
|
|
114
|
+
* call. Mirrors the Rust `conflicts_to_jsonl`. */
|
|
115
|
+
export declare function recordSummaryConflicts(repoPath: string, losers: readonly SummaryShardRecord[]): void;
|
|
116
|
+
/** How many divergence losers are on record. Doctor surfaces this. */
|
|
117
|
+
export declare function countRecordedConflicts(repoPath: string): number;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
3
|
+
export function summariesDir(repoPath) {
|
|
4
|
+
return join(repoPath, ".reposkein", "summaries");
|
|
5
|
+
}
|
|
6
|
+
/** The pre-sharding committed file. Still read (dual-read) for one release. */
|
|
7
|
+
export function legacySummariesPath(repoPath) {
|
|
8
|
+
return join(repoPath, ".reposkein", "summaries.jsonl");
|
|
9
|
+
}
|
|
10
|
+
export function conflictsPath(repoPath) {
|
|
11
|
+
return join(repoPath, ".reposkein", "local", "conflicts.jsonl");
|
|
12
|
+
}
|
|
13
|
+
/** Mirrors the Rust `is_shard_file_name`: exactly two lowercase hex chars. */
|
|
14
|
+
export function isShardFileName(name) {
|
|
15
|
+
return /^[0-9a-f]{2}\.jsonl$/.test(name);
|
|
16
|
+
}
|
|
17
|
+
/** A line git left behind from an unresolved textual merge. A canonical
|
|
18
|
+
* summary line always starts with `{`, so a marker run is damage, not data. */
|
|
19
|
+
export function isConflictMarker(line) {
|
|
20
|
+
return (line.startsWith("<<<<<<<") ||
|
|
21
|
+
line.startsWith("=======") ||
|
|
22
|
+
line.startsWith(">>>>>>>") ||
|
|
23
|
+
line.startsWith("|||||||"));
|
|
24
|
+
}
|
|
25
|
+
/** True for a value that is actually authored prose: a non-empty string.
|
|
26
|
+
* `null`, a number, or `""` all mean "the field is present but says nothing". */
|
|
27
|
+
function isProse(v) {
|
|
28
|
+
return typeof v === "string" && v !== "";
|
|
29
|
+
}
|
|
30
|
+
/** Whether these props carry an authored summary worth keeping.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately identical to the Rust `has_summary`. The two languages read the
|
|
33
|
+
* same committed shards, so a record one accepts and the other rejects is a
|
|
34
|
+
* divergence between what the server serves and what the indexer writes — and
|
|
35
|
+
* a record with nothing in it must never displace one that has prose, in
|
|
36
|
+
* either language. Pinned by the `null-valued`/`non-string` fixture vectors. */
|
|
37
|
+
export function hasSummary(props) {
|
|
38
|
+
return isProse(props.semantic_summary) || isProse(props.purpose_summary);
|
|
39
|
+
}
|
|
40
|
+
function summaryAt(rec) {
|
|
41
|
+
const v = rec.props.summary_at;
|
|
42
|
+
return typeof v === "string" ? v : "";
|
|
43
|
+
}
|
|
44
|
+
/** Byte-lexicographic comparison. JavaScript's `<` compares UTF-16 code units,
|
|
45
|
+
* which orders some astral/BMP pairs differently from the UTF-8 byte order
|
|
46
|
+
* Rust uses. Comparing the encoded bytes is what makes the two languages
|
|
47
|
+
* agree on every input, not just ASCII ones. */
|
|
48
|
+
function lineIsSmaller(a, b) {
|
|
49
|
+
return Buffer.compare(Buffer.from(a, "utf8"), Buffer.from(b, "utf8")) < 0;
|
|
50
|
+
}
|
|
51
|
+
/** Deterministic winner between two records claiming the same node id, when
|
|
52
|
+
* nothing is known about where either came from:
|
|
53
|
+
* newer `summary_at`, then smaller raw line by UTF-8 byte order. Both are
|
|
54
|
+
* pure functions of bytes on disk, so every machine — and the Rust indexer —
|
|
55
|
+
* picks the same winner without coordinating. Kept in lockstep with the Rust
|
|
56
|
+
* `beats` by the shared vectors in `fixtures/summary-shard-vectors.json`.
|
|
57
|
+
*
|
|
58
|
+
* This is the rule for records found in the SAME source (two lines of one
|
|
59
|
+
* merged shard, two agents' sidecars). Across sources of known provenance,
|
|
60
|
+
* use `supersedes`. */
|
|
61
|
+
export function beats(candidate, incumbent) {
|
|
62
|
+
const ca = summaryAt(candidate);
|
|
63
|
+
const ia = summaryAt(incumbent);
|
|
64
|
+
if (ca !== ia)
|
|
65
|
+
return ca > ia;
|
|
66
|
+
return lineIsSmaller(candidate.line, incumbent.line);
|
|
67
|
+
}
|
|
68
|
+
/** Whether a record from a strictly NEWER-provenance source displaces one
|
|
69
|
+
* already held from an older source.
|
|
70
|
+
*
|
|
71
|
+
* `summary_at` is day-precision (PRD §6.2.5 keeps wall-clock time out of
|
|
72
|
+
* committed bytes), so re-summarising a node already summarised today TIES.
|
|
73
|
+
* Resolving that tie by byte order would silently discard the rewrite. A
|
|
74
|
+
* newer source therefore wins unless it is *strictly older* — which is the
|
|
75
|
+
* case that matters, because that is a stale local record about to clobber a
|
|
76
|
+
* teammate's newer one. Mirrors the Rust `supersedes`. */
|
|
77
|
+
export function supersedes(candidate, incumbent) {
|
|
78
|
+
return summaryAt(candidate) >= summaryAt(incumbent);
|
|
79
|
+
}
|
|
80
|
+
export function emptyAccumulator() {
|
|
81
|
+
return { summaries: new Map(), conflicts: [], warnings: [] };
|
|
82
|
+
}
|
|
83
|
+
/** Folds one candidate in, keeping whichever record `wins` selects and
|
|
84
|
+
* preserving the other. The single place a record can be displaced, so no
|
|
85
|
+
* caller can bypass conflict recording by accident. */
|
|
86
|
+
function offer(acc, rec, wins) {
|
|
87
|
+
const existing = acc.summaries.get(rec.id);
|
|
88
|
+
if (!existing) {
|
|
89
|
+
acc.summaries.set(rec.id, rec);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// A union merge duplicating an unchanged line is not a conflict.
|
|
93
|
+
if (existing.line === rec.line)
|
|
94
|
+
return;
|
|
95
|
+
if (wins(rec, existing)) {
|
|
96
|
+
acc.summaries.set(rec.id, rec);
|
|
97
|
+
acc.conflicts.push(existing);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
acc.conflicts.push(rec);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Folds a whole source of strictly NEWER provenance into `acc`. Mirrors the
|
|
104
|
+
* Rust `absorb_source`: displacement uses `supersedes`, and every displaced
|
|
105
|
+
* record is preserved. */
|
|
106
|
+
export function absorbSummarySource(acc, other) {
|
|
107
|
+
for (const rec of other.summaries.values())
|
|
108
|
+
offer(acc, rec, supersedes);
|
|
109
|
+
acc.conflicts.push(...other.conflicts);
|
|
110
|
+
acc.warnings.push(...other.warnings);
|
|
111
|
+
}
|
|
112
|
+
/** Folds one file's text in, resolving same-source records with `beats`.
|
|
113
|
+
* Exported for the shared vectors. */
|
|
114
|
+
export function absorbSummaryLines(acc, source, text) {
|
|
115
|
+
let markers = 0;
|
|
116
|
+
let malformed = 0;
|
|
117
|
+
for (const raw of text.split("\n")) {
|
|
118
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
119
|
+
if (line.trim() === "")
|
|
120
|
+
continue;
|
|
121
|
+
if (isConflictMarker(line)) {
|
|
122
|
+
markers++;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
let obj;
|
|
126
|
+
try {
|
|
127
|
+
const parsed = JSON.parse(line);
|
|
128
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
129
|
+
malformed++;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
obj = parsed;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
malformed++;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const id = obj.id;
|
|
139
|
+
if (typeof id !== "string" || id === "") {
|
|
140
|
+
malformed++;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const { id: _drop, ...props } = obj;
|
|
144
|
+
// A line with no authored prose is not a summary. Letting it into the map
|
|
145
|
+
// would let it WIN a tiebreak against a real summary and evict it — see
|
|
146
|
+
// `hasSummary` for the null-valued case that did exactly that.
|
|
147
|
+
if (!hasSummary(props)) {
|
|
148
|
+
malformed++;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
offer(acc, { id, props, line }, beats);
|
|
152
|
+
}
|
|
153
|
+
if (markers > 0) {
|
|
154
|
+
acc.warnings.push(`${source}: skipped ${markers} git conflict-marker line(s); run \`reposkein-indexer index\` to rewrite the shard cleanly`);
|
|
155
|
+
}
|
|
156
|
+
if (malformed > 0) {
|
|
157
|
+
acc.warnings.push(`${source}: skipped ${malformed} malformed line(s)`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Reads every committed shard plus the pre-sharding file, tolerantly.
|
|
161
|
+
* A missing directory is the normal state for a repo with no authored prose,
|
|
162
|
+
* and returns an empty result rather than an error. */
|
|
163
|
+
export function loadSummaryShards(repoPath) {
|
|
164
|
+
const acc = emptyAccumulator();
|
|
165
|
+
const dir = summariesDir(repoPath);
|
|
166
|
+
let names = [];
|
|
167
|
+
try {
|
|
168
|
+
names = readdirSync(dir).filter(isShardFileName).sort();
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
names = [];
|
|
172
|
+
}
|
|
173
|
+
for (const name of names) {
|
|
174
|
+
try {
|
|
175
|
+
absorbSummaryLines(acc, `summaries/${name}`, readFileSync(join(dir, name), "utf8"));
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
acc.warnings.push(`summaries/${name}: unreadable`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const legacy = legacySummariesPath(repoPath);
|
|
182
|
+
const legacyFilePresent = existsSync(legacy);
|
|
183
|
+
if (legacyFilePresent) {
|
|
184
|
+
try {
|
|
185
|
+
absorbSummaryLines(acc, "summaries.jsonl", readFileSync(legacy, "utf8"));
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
acc.warnings.push("summaries.jsonl: unreadable");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Sorted by id so callers iterate deterministically.
|
|
192
|
+
const summaries = new Map([...acc.summaries.entries()].sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)));
|
|
193
|
+
return { summaries, conflicts: acc.conflicts, warnings: acc.warnings, legacyFilePresent };
|
|
194
|
+
}
|
|
195
|
+
/** A cheap fingerprint of everything the summary overlay reads on disk.
|
|
196
|
+
*
|
|
197
|
+
* The store keys its reload on this, so a `git pull` that brings in a
|
|
198
|
+
* teammate's shards — or another agent's sidecar write on this machine — is
|
|
199
|
+
* visible without restarting the process. Stat calls only, O(shards +
|
|
200
|
+
* sidecars), no content read, because this runs on every read and not just on
|
|
201
|
+
* change. mtime alone is not enough on filesystems with coarse timestamps, so
|
|
202
|
+
* size rides along.
|
|
203
|
+
*
|
|
204
|
+
* `sidecarFiles` is injected rather than imported to keep this module free of
|
|
205
|
+
* a cycle with sidecar.ts, which imports the fold from here. */
|
|
206
|
+
export function summaryShardsStamp(repoPath, sidecarFiles = () => []) {
|
|
207
|
+
const parts = [];
|
|
208
|
+
const dir = summariesDir(repoPath);
|
|
209
|
+
let names = [];
|
|
210
|
+
try {
|
|
211
|
+
names = readdirSync(dir).filter(isShardFileName).sort();
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
names = [];
|
|
215
|
+
}
|
|
216
|
+
for (const name of names) {
|
|
217
|
+
try {
|
|
218
|
+
const s = statSync(join(dir, name));
|
|
219
|
+
parts.push(`${name}:${s.mtimeMs}:${s.size}`);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
parts.push(`${name}:?`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const s = statSync(legacySummariesPath(repoPath));
|
|
227
|
+
parts.push(`legacy:${s.mtimeMs}:${s.size}`);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// absent, which is the post-migration norm
|
|
231
|
+
}
|
|
232
|
+
// Sidecars too. Without them a second agent's write on the same checkout was
|
|
233
|
+
// invisible to an already-open server for the life of the process — which
|
|
234
|
+
// the overlay explicitly promises to surface.
|
|
235
|
+
for (const p of sidecarFiles(repoPath)) {
|
|
236
|
+
try {
|
|
237
|
+
const s = statSync(p);
|
|
238
|
+
parts.push(`sc/${basename(p)}:${s.mtimeMs}:${s.size}`);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
parts.push(`sc/${basename(p)}:?`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return parts.join("|");
|
|
245
|
+
}
|
|
246
|
+
/** Merges divergence losers into the git-ignored `local/conflicts.jsonl`.
|
|
247
|
+
*
|
|
248
|
+
* Deduped and sorted, so repeated reads converge instead of growing the file,
|
|
249
|
+
* and never truncating: a loser recorded by an earlier run (or by the indexer)
|
|
250
|
+
* stays. Best-effort — failing to record a conflict must not break a tool
|
|
251
|
+
* call. Mirrors the Rust `conflicts_to_jsonl`. */
|
|
252
|
+
export function recordSummaryConflicts(repoPath, losers) {
|
|
253
|
+
if (losers.length === 0)
|
|
254
|
+
return;
|
|
255
|
+
const path = conflictsPath(repoPath);
|
|
256
|
+
const lines = new Set();
|
|
257
|
+
try {
|
|
258
|
+
for (const raw of readFileSync(path, "utf8").split("\n")) {
|
|
259
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
260
|
+
if (line.trim() !== "" && !isConflictMarker(line))
|
|
261
|
+
lines.add(line);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// no existing file
|
|
266
|
+
}
|
|
267
|
+
const before = lines.size;
|
|
268
|
+
for (const l of losers)
|
|
269
|
+
lines.add(l.line);
|
|
270
|
+
if (lines.size === before)
|
|
271
|
+
return;
|
|
272
|
+
try {
|
|
273
|
+
mkdirSync(join(repoPath, ".reposkein", "local"), { recursive: true });
|
|
274
|
+
writeFileSync(path, [...lines].sort().join("\n") + "\n");
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// best-effort
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/** How many divergence losers are on record. Doctor surfaces this. */
|
|
281
|
+
export function countRecordedConflicts(repoPath) {
|
|
282
|
+
try {
|
|
283
|
+
return readFileSync(conflictsPath(repoPath), "utf8")
|
|
284
|
+
.split("\n")
|
|
285
|
+
.filter((l) => l.trim() !== "").length;
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return 0;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=summaryShards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summaryShards.js","sourceRoot":"","sources":["../../src/store/summaryShards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Reads `pages_url` from the `[team]` section of `.reposkein/config.toml`,
|
|
2
|
+
* or null when the file/section/key is absent (the common case — this is
|
|
3
|
+
* an opt-in field a team adds after publishing a hosted constellation, see
|
|
4
|
+
* docs/HOSTING.md). Points the viewer's header at wherever the team's
|
|
5
|
+
* canonical/CI-published constellation lives (e.g. a GitHub Pages URL),
|
|
6
|
+
* distinct from whatever ad-hoc `view`/`view --export` a given machine
|
|
7
|
+
* happens to be looking at right now.
|
|
8
|
+
*
|
|
9
|
+
* A deliberate ~20-line scanner rather than a TOML dependency — mirrors
|
|
10
|
+
* `config_bool` in indexer/crates/cli/src/main.rs: this reads exactly one
|
|
11
|
+
* setting, and its config is a file `reposkein-indexer init` writes.
|
|
12
|
+
* Absent file, section, or key all mean `null`. */
|
|
13
|
+
export declare function readTeamPagesUrl(repoPath: string): string | null;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
/** Reads `pages_url` from the `[team]` section of `.reposkein/config.toml`,
|
|
4
|
+
* or null when the file/section/key is absent (the common case — this is
|
|
5
|
+
* an opt-in field a team adds after publishing a hosted constellation, see
|
|
6
|
+
* docs/HOSTING.md). Points the viewer's header at wherever the team's
|
|
7
|
+
* canonical/CI-published constellation lives (e.g. a GitHub Pages URL),
|
|
8
|
+
* distinct from whatever ad-hoc `view`/`view --export` a given machine
|
|
9
|
+
* happens to be looking at right now.
|
|
10
|
+
*
|
|
11
|
+
* A deliberate ~20-line scanner rather than a TOML dependency — mirrors
|
|
12
|
+
* `config_bool` in indexer/crates/cli/src/main.rs: this reads exactly one
|
|
13
|
+
* setting, and its config is a file `reposkein-indexer init` writes.
|
|
14
|
+
* Absent file, section, or key all mean `null`. */
|
|
15
|
+
export function readTeamPagesUrl(repoPath) {
|
|
16
|
+
const path = join(repoPath, ".reposkein", "config.toml");
|
|
17
|
+
if (!existsSync(path))
|
|
18
|
+
return null;
|
|
19
|
+
let text;
|
|
20
|
+
try {
|
|
21
|
+
text = readFileSync(path, "utf8");
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
let inTeamSection = false;
|
|
27
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
28
|
+
const line = rawLine.trim();
|
|
29
|
+
if (line === "" || line.startsWith("#"))
|
|
30
|
+
continue;
|
|
31
|
+
if (line.startsWith("[")) {
|
|
32
|
+
inTeamSection = line === "[team]";
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!inTeamSection)
|
|
36
|
+
continue;
|
|
37
|
+
const eq = line.indexOf("=");
|
|
38
|
+
if (eq === -1)
|
|
39
|
+
continue;
|
|
40
|
+
const key = line.slice(0, eq).trim();
|
|
41
|
+
if (key !== "pages_url")
|
|
42
|
+
continue;
|
|
43
|
+
const rawValue = line.slice(eq + 1).split("#")[0].trim();
|
|
44
|
+
const quoted = rawValue.match(/^"([^"]*)"$/) ?? rawValue.match(/^'([^']*)'$/);
|
|
45
|
+
return quoted ? quoted[1] : null;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=teamConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teamConfig.js","sourceRoot":"","sources":["../../src/store/teamConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;;oDAWoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACzD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,aAAa,GAAG,IAAI,KAAK,QAAQ,CAAC;YAClC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,aAAa;YAAE,SAAS;QAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAS;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,IAAI,GAAG,KAAK,WAAW;YAAE,SAAS;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9E,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -22,8 +22,20 @@ export interface InitArgs {
|
|
|
22
22
|
path?: string;
|
|
23
23
|
full?: boolean;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
/** `path` (the repo to index) MUST come from the caller's already-resolved
|
|
26
|
+
* active repo (mcp/src/store/repoSession.ts), not re-derived here — this
|
|
27
|
+
* tool used to default to REPOSKEIN_REPO_PATH/cwd internally via
|
|
28
|
+
* runIndexer.js's `repoPath()`, which bypassed session.select_repo entirely
|
|
29
|
+
* and could index the wrong repo in workspace mode. Args-supplied `path`
|
|
30
|
+
* still wins, matching the original "explicit arg beats everything" rule. */
|
|
31
|
+
export declare function makeInitCpgSkeleton(repoId: string, repoPath: string, deps?: Partial<IndexerDeps>): (args: InitArgs) => Promise<ToolResult>;
|
|
26
32
|
export interface ReindexArgs {
|
|
27
33
|
path: string;
|
|
28
34
|
}
|
|
29
|
-
|
|
35
|
+
/** `path` has no override — `reindex_file`'s args only carry the file being
|
|
36
|
+
* reindexed, not a repo root — so this ALWAYS targets the caller's resolved
|
|
37
|
+
* active repo. Same reasoning as `makeInitCpgSkeleton` above: previously
|
|
38
|
+
* this read REPOSKEIN_REPO_PATH/cwd internally, independent of
|
|
39
|
+
* session.select_repo — the exact "reindex the wrong repo" bug class this
|
|
40
|
+
* parameter exists to close. */
|
|
41
|
+
export declare function makeReindexFile(repoId: string, repoPath: string, deps?: Partial<IndexerDeps>): (args: ReindexArgs) => Promise<ToolResult>;
|