projscan 3.5.0 → 3.6.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 (60) hide show
  1. package/README.md +26 -21
  2. package/dist/cli/commands/claim.d.ts +5 -0
  3. package/dist/cli/commands/claim.js +139 -0
  4. package/dist/cli/commands/claim.js.map +1 -0
  5. package/dist/cli/commands/collision.d.ts +5 -0
  6. package/dist/cli/commands/collision.js +55 -0
  7. package/dist/cli/commands/collision.js.map +1 -0
  8. package/dist/cli/commands/coordinate.d.ts +5 -0
  9. package/dist/cli/commands/coordinate.js +43 -0
  10. package/dist/cli/commands/coordinate.js.map +1 -0
  11. package/dist/cli/commands/mergeRisk.d.ts +5 -0
  12. package/dist/cli/commands/mergeRisk.js +58 -0
  13. package/dist/cli/commands/mergeRisk.js.map +1 -0
  14. package/dist/cli/commands/route.d.ts +5 -0
  15. package/dist/cli/commands/route.js +53 -0
  16. package/dist/cli/commands/route.js.map +1 -0
  17. package/dist/cli/index.js +10 -0
  18. package/dist/cli/index.js.map +1 -1
  19. package/dist/core/claims.d.ts +60 -0
  20. package/dist/core/claims.js +139 -0
  21. package/dist/core/claims.js.map +1 -0
  22. package/dist/core/collisionDetector.d.ts +55 -0
  23. package/dist/core/collisionDetector.js +156 -0
  24. package/dist/core/collisionDetector.js.map +1 -0
  25. package/dist/core/coordination.d.ts +49 -0
  26. package/dist/core/coordination.js +71 -0
  27. package/dist/core/coordination.js.map +1 -0
  28. package/dist/core/embeddings.js +30 -17
  29. package/dist/core/embeddings.js.map +1 -1
  30. package/dist/core/intentRouter.d.ts +40 -0
  31. package/dist/core/intentRouter.js +213 -0
  32. package/dist/core/intentRouter.js.map +1 -0
  33. package/dist/core/mergeRisk.d.ts +42 -0
  34. package/dist/core/mergeRisk.js +71 -0
  35. package/dist/core/mergeRisk.js.map +1 -0
  36. package/dist/core/roadmapCatalog.js +50 -50
  37. package/dist/core/roadmapCatalog.js.map +1 -1
  38. package/dist/mcp/tools/claim.d.ts +7 -0
  39. package/dist/mcp/tools/claim.js +69 -0
  40. package/dist/mcp/tools/claim.js.map +1 -0
  41. package/dist/mcp/tools/collision.d.ts +7 -0
  42. package/dist/mcp/tools/collision.js +24 -0
  43. package/dist/mcp/tools/collision.js.map +1 -0
  44. package/dist/mcp/tools/coordinate.d.ts +7 -0
  45. package/dist/mcp/tools/coordinate.js +24 -0
  46. package/dist/mcp/tools/coordinate.js.map +1 -0
  47. package/dist/mcp/tools/mergeRisk.d.ts +7 -0
  48. package/dist/mcp/tools/mergeRisk.js +24 -0
  49. package/dist/mcp/tools/mergeRisk.js.map +1 -0
  50. package/dist/mcp/tools/route.d.ts +7 -0
  51. package/dist/mcp/tools/route.js +24 -0
  52. package/dist/mcp/tools/route.js.map +1 -0
  53. package/dist/mcp/tools.js +10 -0
  54. package/dist/mcp/tools.js.map +1 -1
  55. package/dist/projscan-sbom.cdx.json +6 -6
  56. package/dist/tool-manifest.json +94 -3
  57. package/dist/utils/formatSupport.d.ts +9 -0
  58. package/dist/utils/formatSupport.js +9 -0
  59. package/dist/utils/formatSupport.js.map +1 -1
  60. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -17,6 +17,11 @@ import { registerReview } from './commands/review.js';
17
17
  import { registerFixSuggest } from './commands/fixSuggest.js';
18
18
  import { registerExplainIssue } from './commands/explainIssue.js';
19
19
  import { registerImpact } from './commands/impact.js';
20
+ import { registerCollision } from './commands/collision.js';
21
+ import { registerClaim } from './commands/claim.js';
22
+ import { registerMergeRisk } from './commands/mergeRisk.js';
23
+ import { registerRoute } from './commands/route.js';
24
+ import { registerCoordinate } from './commands/coordinate.js';
20
25
  import { registerWatch } from './commands/watch.js';
21
26
  import { registerWorkspaces } from './commands/workspaces.js';
22
27
  import { registerOutdated } from './commands/outdated.js';
@@ -70,6 +75,11 @@ registerReview();
70
75
  registerFixSuggest();
71
76
  registerExplainIssue();
72
77
  registerImpact();
78
+ registerCollision();
79
+ registerClaim();
80
+ registerMergeRisk();
81
+ registerRoute();
82
+ registerCoordinate();
73
83
  registerWatch();
74
84
  registerWorkspaces();
75
85
  registerOutdated();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Swarm claims / leases (4.x coordination arc).
3
+ *
4
+ * An agent can claim a file, directory, or symbol so the rest of the swarm sees
5
+ * who is working where. Claims are advisory (not a hard lock) — claiming an
6
+ * already-claimed target still succeeds, but returns the contending claims so
7
+ * the agent can coordinate.
8
+ *
9
+ * The store is shared across all git worktrees of the repo: it lives under the
10
+ * **git common dir** (`git rev-parse --git-common-dir`), not the per-worktree
11
+ * `.projscan-cache`, because two agents coordinating are in different worktrees
12
+ * of the same repo. Strictly local-first — no network, no server.
13
+ */
14
+ export interface Claim {
15
+ id: string;
16
+ /** Claimed target: a repo-relative file/dir path, or a symbol name. */
17
+ target: string;
18
+ /** Who holds the claim. */
19
+ agent: string;
20
+ note?: string;
21
+ /** ISO timestamp. */
22
+ claimedAt: string;
23
+ /** ISO expiry (lease). Absent = never expires. */
24
+ expiresAt?: string;
25
+ }
26
+ export interface AddClaimResult {
27
+ claim: Claim;
28
+ /** Existing claims by OTHER agents whose target overlaps this one. */
29
+ contention: Claim[];
30
+ }
31
+ /** Two targets overlap if equal, or one is a directory ancestor of the other. */
32
+ export declare function claimTargetsOverlap(a: string, b: string): boolean;
33
+ /** Claims held by more than one agent on overlapping targets (contention). */
34
+ export declare function findContendedClaims(claims: Claim[]): Claim[];
35
+ /** All active claims, shared across the repo's worktrees. */
36
+ export declare function listClaims(rootPath: string): Promise<Claim[]>;
37
+ /**
38
+ * Record a claim. Returns the new claim plus any contending claims (held by a
39
+ * different agent on an overlapping target). The claim is recorded regardless —
40
+ * it's advisory; contention is surfaced for the agent to act on.
41
+ */
42
+ export declare function addClaim(rootPath: string, input: {
43
+ target: string;
44
+ agent: string;
45
+ note?: string;
46
+ ttlSeconds?: number;
47
+ }, now?: () => Date): Promise<AddClaimResult>;
48
+ /** A claim is active unless its lease (expiresAt) has passed. No expiry = active. */
49
+ export declare function isClaimActive(claim: Claim, now?: Date): boolean;
50
+ /** Remove expired-lease claims. Returns the claims that were pruned. */
51
+ export declare function pruneClaims(rootPath: string, now?: Date): Promise<Claim[]>;
52
+ /**
53
+ * Release claims by id, by target (optionally scoped to an agent), or all of an
54
+ * agent's claims. Returns the claims that were removed.
55
+ */
56
+ export declare function releaseClaim(rootPath: string, selector: {
57
+ id?: string;
58
+ target?: string;
59
+ agent?: string;
60
+ }): Promise<Claim[]>;
@@ -0,0 +1,139 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import { randomUUID } from 'node:crypto';
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { atomicWriteFile } from '../utils/atomicWrite.js';
7
+ const execFileAsync = promisify(execFile);
8
+ async function claimStorePath(rootPath) {
9
+ try {
10
+ const { stdout } = await execFileAsync('git', ['rev-parse', '--git-common-dir'], { cwd: rootPath });
11
+ // --git-common-dir is the SAME directory for every worktree of the repo, so
12
+ // the claim store is shared across the swarm. It may be relative to cwd.
13
+ return path.join(path.resolve(rootPath, stdout.trim()), 'projscan', 'claims.json');
14
+ }
15
+ catch {
16
+ // Not a git repo — fall back to the local cache (single-worktree only).
17
+ return path.join(rootPath, '.projscan-cache', 'claims.json');
18
+ }
19
+ }
20
+ /** Normalize a target for comparison: POSIX separators, no trailing slash. */
21
+ function normalizeTarget(target) {
22
+ const t = target.trim().split('\\').join('/');
23
+ return t.endsWith('/') && t.length > 1 ? t.slice(0, -1) : t;
24
+ }
25
+ /** Two targets overlap if equal, or one is a directory ancestor of the other. */
26
+ export function claimTargetsOverlap(a, b) {
27
+ const na = normalizeTarget(a);
28
+ const nb = normalizeTarget(b);
29
+ if (na === nb)
30
+ return true;
31
+ return nb.startsWith(`${na}/`) || na.startsWith(`${nb}/`);
32
+ }
33
+ /** Claims held by more than one agent on overlapping targets (contention). */
34
+ export function findContendedClaims(claims) {
35
+ const contended = new Set();
36
+ for (let i = 0; i < claims.length; i++) {
37
+ for (let j = i + 1; j < claims.length; j++) {
38
+ if (claims[i].agent !== claims[j].agent && claimTargetsOverlap(claims[i].target, claims[j].target)) {
39
+ contended.add(claims[i]);
40
+ contended.add(claims[j]);
41
+ }
42
+ }
43
+ }
44
+ return [...contended];
45
+ }
46
+ function isWellShapedClaim(value) {
47
+ if (!value || typeof value !== 'object')
48
+ return false;
49
+ const c = value;
50
+ return (typeof c.id === 'string' &&
51
+ typeof c.target === 'string' &&
52
+ typeof c.agent === 'string' &&
53
+ typeof c.claimedAt === 'string');
54
+ }
55
+ async function readStore(rootPath) {
56
+ try {
57
+ const raw = await fs.readFile(await claimStorePath(rootPath), 'utf-8');
58
+ const parsed = JSON.parse(raw);
59
+ const claims = Array.isArray(parsed.claims) ? parsed.claims.filter(isWellShapedClaim) : [];
60
+ return { schemaVersion: 1, claims };
61
+ }
62
+ catch {
63
+ return { schemaVersion: 1, claims: [] };
64
+ }
65
+ }
66
+ async function writeStore(rootPath, store) {
67
+ const file = await claimStorePath(rootPath);
68
+ await fs.mkdir(path.dirname(file), { recursive: true });
69
+ await atomicWriteFile(file, JSON.stringify(store, null, 2) + '\n');
70
+ }
71
+ /** All active claims, shared across the repo's worktrees. */
72
+ export async function listClaims(rootPath) {
73
+ return (await readStore(rootPath)).claims;
74
+ }
75
+ /**
76
+ * Record a claim. Returns the new claim plus any contending claims (held by a
77
+ * different agent on an overlapping target). The claim is recorded regardless —
78
+ * it's advisory; contention is surfaced for the agent to act on.
79
+ */
80
+ export async function addClaim(rootPath, input, now = () => new Date()) {
81
+ const target = normalizeTarget(input.target);
82
+ const at = now();
83
+ const store = await readStore(rootPath);
84
+ // Only ACTIVE claims (not expired leases) by a different agent contend.
85
+ const contention = store.claims.filter((c) => c.agent !== input.agent && isClaimActive(c, at) && claimTargetsOverlap(c.target, target));
86
+ const claim = {
87
+ id: randomUUID(),
88
+ target,
89
+ agent: input.agent,
90
+ ...(input.note ? { note: input.note } : {}),
91
+ claimedAt: at.toISOString(),
92
+ ...(input.ttlSeconds && input.ttlSeconds > 0
93
+ ? { expiresAt: new Date(at.getTime() + input.ttlSeconds * 1000).toISOString() }
94
+ : {}),
95
+ };
96
+ store.claims.push(claim);
97
+ await writeStore(rootPath, store);
98
+ return { claim, contention };
99
+ }
100
+ /** A claim is active unless its lease (expiresAt) has passed. No expiry = active. */
101
+ export function isClaimActive(claim, now = new Date()) {
102
+ if (!claim.expiresAt)
103
+ return true;
104
+ return new Date(claim.expiresAt).getTime() > now.getTime();
105
+ }
106
+ /** Remove expired-lease claims. Returns the claims that were pruned. */
107
+ export async function pruneClaims(rootPath, now = new Date()) {
108
+ const store = await readStore(rootPath);
109
+ const pruned = store.claims.filter((c) => !isClaimActive(c, now));
110
+ if (pruned.length === 0)
111
+ return [];
112
+ store.claims = store.claims.filter((c) => isClaimActive(c, now));
113
+ await writeStore(rootPath, store);
114
+ return pruned;
115
+ }
116
+ /**
117
+ * Release claims by id, by target (optionally scoped to an agent), or all of an
118
+ * agent's claims. Returns the claims that were removed.
119
+ */
120
+ export async function releaseClaim(rootPath, selector) {
121
+ const store = await readStore(rootPath);
122
+ const target = selector.target !== undefined ? normalizeTarget(selector.target) : undefined;
123
+ const matches = (c) => {
124
+ if (selector.id !== undefined)
125
+ return c.id === selector.id;
126
+ if (target !== undefined)
127
+ return c.target === target && (selector.agent === undefined || c.agent === selector.agent);
128
+ if (selector.agent !== undefined)
129
+ return c.agent === selector.agent;
130
+ return false;
131
+ };
132
+ const removed = store.claims.filter(matches);
133
+ if (removed.length === 0)
134
+ return [];
135
+ store.claims = store.claims.filter((c) => !matches(c));
136
+ await writeStore(rootPath, store);
137
+ return removed;
138
+ }
139
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/core/claims.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Swarm collision detection (4.x coordination arc).
3
+ *
4
+ * When several agents edit one repo in parallel — each in its own git worktree
5
+ * — their changes collide if they touch the same file, or if one edits a file
6
+ * the other's change depends on. This surfaces those overlaps BEFORE the
7
+ * branches are merged, using the existing import graph for blast radius.
8
+ *
9
+ * Strictly local-first: it reads the repo's own `git worktree list` (same
10
+ * machine, same repo) and never reaches the network or a coordination server.
11
+ */
12
+ export interface WorktreeRef {
13
+ /** Absolute worktree path. */
14
+ path: string;
15
+ /** Branch name (no refs/heads/ prefix), or null when detached. */
16
+ branch: string | null;
17
+ /** HEAD commit sha, or null. */
18
+ head: string | null;
19
+ }
20
+ export type CollisionKind = 'same-file' | 'dependency';
21
+ export interface Collision {
22
+ kind: CollisionKind;
23
+ severity: 'high' | 'medium';
24
+ worktreeA: string;
25
+ fileA: string;
26
+ worktreeB: string;
27
+ fileB: string;
28
+ reason: string;
29
+ }
30
+ export interface CollisionWorktreeSummary {
31
+ path: string;
32
+ branch: string | null;
33
+ changedFileCount: number;
34
+ baseRef: string | null;
35
+ }
36
+ export interface CollisionReport {
37
+ schemaVersion: 1;
38
+ available: boolean;
39
+ reason?: string;
40
+ worktrees: CollisionWorktreeSummary[];
41
+ collisions: Collision[];
42
+ }
43
+ export interface DetectCollisionsOptions {
44
+ /** Base ref each worktree is diffed against. Defaults to the usual fallbacks. */
45
+ baseRef?: string;
46
+ }
47
+ /** Parse `git worktree list --porcelain` into structured refs. Local-first. */
48
+ export declare function listWorktrees(rootPath: string): Promise<WorktreeRef[]>;
49
+ /**
50
+ * Detect collisions across the repo's in-flight worktrees. Needs at least two
51
+ * worktrees (otherwise there's nothing to coordinate). The dependency edges
52
+ * come from the current repo's import graph (HEAD); a file added only inside a
53
+ * worktree simply has no edges yet and is still caught by same-file overlap.
54
+ */
55
+ export declare function detectCollisions(rootPath: string, options?: DetectCollisionsOptions): Promise<CollisionReport>;
@@ -0,0 +1,156 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import { scanRepository } from './repositoryScanner.js';
4
+ import { buildCodeGraph, importersOf } from './codeGraph.js';
5
+ import { getChangedFiles } from '../utils/changedFiles.js';
6
+ const execFileAsync = promisify(execFile);
7
+ /** Parse `git worktree list --porcelain` into structured refs. Local-first. */
8
+ export async function listWorktrees(rootPath) {
9
+ let stdout;
10
+ try {
11
+ ({ stdout } = await execFileAsync('git', ['worktree', 'list', '--porcelain'], {
12
+ cwd: rootPath,
13
+ maxBuffer: 8 * 1024 * 1024,
14
+ }));
15
+ }
16
+ catch {
17
+ return [];
18
+ }
19
+ const refs = [];
20
+ let current = null;
21
+ const flush = () => {
22
+ if (current)
23
+ refs.push(current);
24
+ current = null;
25
+ };
26
+ for (const line of stdout.split('\n')) {
27
+ if (line.startsWith('worktree ')) {
28
+ flush();
29
+ current = { path: line.slice('worktree '.length).trim(), branch: null, head: null };
30
+ }
31
+ else if (current && line.startsWith('HEAD ')) {
32
+ current.head = line.slice('HEAD '.length).trim();
33
+ }
34
+ else if (current && line.startsWith('branch ')) {
35
+ current.branch = line.slice('branch '.length).trim().replace(/^refs\/heads\//, '');
36
+ }
37
+ else if (current && line.trim() === 'detached') {
38
+ current.branch = null;
39
+ }
40
+ else if (line.trim() === '') {
41
+ flush();
42
+ }
43
+ }
44
+ flush();
45
+ return refs;
46
+ }
47
+ /**
48
+ * Detect collisions across the repo's in-flight worktrees. Needs at least two
49
+ * worktrees (otherwise there's nothing to coordinate). The dependency edges
50
+ * come from the current repo's import graph (HEAD); a file added only inside a
51
+ * worktree simply has no edges yet and is still caught by same-file overlap.
52
+ */
53
+ export async function detectCollisions(rootPath, options = {}) {
54
+ const worktrees = await listWorktrees(rootPath);
55
+ if (worktrees.length < 2) {
56
+ return {
57
+ schemaVersion: 1,
58
+ available: false,
59
+ reason: worktrees.length === 0
60
+ ? 'not a git repository, or git worktrees are unavailable'
61
+ : 'only one worktree — collision detection needs at least two in-flight worktrees',
62
+ worktrees: worktrees.map((w) => ({ path: w.path, branch: w.branch, changedFileCount: 0, baseRef: null })),
63
+ collisions: [],
64
+ };
65
+ }
66
+ // Changed files per worktree (repo-relative, POSIX).
67
+ const changes = await Promise.all(worktrees.map(async (w) => {
68
+ const result = await getChangedFiles(w.path, options.baseRef);
69
+ return {
70
+ ref: w,
71
+ files: result.available ? result.files : [],
72
+ baseRef: result.baseRef,
73
+ };
74
+ }));
75
+ // Import graph of the current repo for dependency (blast-radius) edges.
76
+ const scan = await scanRepository(rootPath);
77
+ const graph = await buildCodeGraph(rootPath, scan.files);
78
+ const collisions = [];
79
+ for (let i = 0; i < changes.length; i++) {
80
+ for (let j = i + 1; j < changes.length; j++) {
81
+ const a = changes[i];
82
+ const b = changes[j];
83
+ const aFiles = a.files;
84
+ const bSet = new Set(b.files);
85
+ const aSet = new Set(a.files);
86
+ // Same-file overlap — both worktrees changed the same file.
87
+ for (const file of aFiles) {
88
+ if (bSet.has(file)) {
89
+ collisions.push({
90
+ kind: 'same-file',
91
+ severity: 'high',
92
+ worktreeA: a.ref.path,
93
+ fileA: file,
94
+ worktreeB: b.ref.path,
95
+ fileB: file,
96
+ reason: `Both worktrees changed ${file}.`,
97
+ });
98
+ }
99
+ }
100
+ // Dependency overlap — one worktree changed a file the other's change
101
+ // imports (1-hop import edge). Skip files already flagged same-file.
102
+ for (const file of aFiles) {
103
+ if (bSet.has(file))
104
+ continue;
105
+ const importers = new Set(importersOf(graph, file));
106
+ for (const other of b.files) {
107
+ if (other === file || aSet.has(other))
108
+ continue;
109
+ if (importers.has(other)) {
110
+ collisions.push({
111
+ kind: 'dependency',
112
+ severity: 'medium',
113
+ worktreeA: a.ref.path,
114
+ fileA: file,
115
+ worktreeB: b.ref.path,
116
+ fileB: other,
117
+ reason: `${other} (changed in the other worktree) imports ${file} (changed here).`,
118
+ });
119
+ }
120
+ }
121
+ }
122
+ for (const file of b.files) {
123
+ if (aSet.has(file))
124
+ continue;
125
+ const importers = new Set(importersOf(graph, file));
126
+ for (const other of aFiles) {
127
+ if (other === file || bSet.has(other))
128
+ continue;
129
+ if (importers.has(other)) {
130
+ collisions.push({
131
+ kind: 'dependency',
132
+ severity: 'medium',
133
+ worktreeA: a.ref.path,
134
+ fileA: other,
135
+ worktreeB: b.ref.path,
136
+ fileB: file,
137
+ reason: `${other} (changed here) imports ${file} (changed in the other worktree).`,
138
+ });
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ return {
145
+ schemaVersion: 1,
146
+ available: true,
147
+ worktrees: changes.map((c) => ({
148
+ path: c.ref.path,
149
+ branch: c.ref.branch,
150
+ changedFileCount: c.files.length,
151
+ baseRef: c.baseRef,
152
+ })),
153
+ collisions,
154
+ };
155
+ }
156
+ //# sourceMappingURL=collisionDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collisionDetector.js","sourceRoot":"","sources":["../../src/core/collisionDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type CollisionReport } from './collisionDetector.js';
2
+ import { type Claim } from './claims.js';
3
+ import { type MergeRiskReport } from './mergeRisk.js';
4
+ /**
5
+ * Coordination summary (4.x arc, epic 5 — the capstone).
6
+ *
7
+ * Composes the three swarm primitives — collisions, claims, and merge-risk —
8
+ * into one budget-shaped read with a `readiness` verdict, so an agent gets a
9
+ * single coordination signal instead of three calls. It is also the arc's
10
+ * measurable outcome surface: the counts (collisions caught, contended claims,
11
+ * merge hotspots) quantify what the coordination layer surfaced. Local-first.
12
+ */
13
+ export type CoordinationReadiness = 'clear' | 'caution' | 'conflicted';
14
+ export interface CoordinationSummary {
15
+ schemaVersion: 1;
16
+ available: boolean;
17
+ reason?: string;
18
+ worktreeCount: number;
19
+ collisions: {
20
+ total: number;
21
+ high: number;
22
+ medium: number;
23
+ };
24
+ claims: {
25
+ total: number;
26
+ contendedTargets: number;
27
+ };
28
+ mergeRisk: {
29
+ hotspotCount: number;
30
+ integrationOrder: Array<{
31
+ worktree: string;
32
+ branch: string | null;
33
+ riskScore: number;
34
+ }>;
35
+ };
36
+ readiness: CoordinationReadiness;
37
+ summary: string[];
38
+ }
39
+ export interface CoordinationInputs {
40
+ collisionReport: CollisionReport;
41
+ claims: Claim[];
42
+ mergeRisk: MergeRiskReport;
43
+ }
44
+ /** Pure: fold the three swarm signals into a summary + readiness verdict. */
45
+ export declare function summarizeCoordination(inputs: CoordinationInputs): CoordinationSummary;
46
+ /** Run the full coordination read for the repo's in-flight worktrees. */
47
+ export declare function computeCoordination(rootPath: string, options?: {
48
+ baseRef?: string;
49
+ }): Promise<CoordinationSummary>;
@@ -0,0 +1,71 @@
1
+ import { detectCollisions } from './collisionDetector.js';
2
+ import { listClaims, findContendedClaims } from './claims.js';
3
+ import { computeMergeRisk } from './mergeRisk.js';
4
+ /** Pure: fold the three swarm signals into a summary + readiness verdict. */
5
+ export function summarizeCoordination(inputs) {
6
+ const { collisionReport, claims, mergeRisk } = inputs;
7
+ if (!collisionReport.available) {
8
+ return {
9
+ schemaVersion: 1,
10
+ available: false,
11
+ ...(collisionReport.reason ? { reason: collisionReport.reason } : {}),
12
+ worktreeCount: collisionReport.worktrees.length,
13
+ collisions: { total: 0, high: 0, medium: 0 },
14
+ claims: { total: claims.length, contendedTargets: 0 },
15
+ mergeRisk: { hotspotCount: 0, integrationOrder: [] },
16
+ readiness: 'clear',
17
+ summary: [collisionReport.reason ?? 'Coordination unavailable.'],
18
+ };
19
+ }
20
+ const high = collisionReport.collisions.filter((c) => c.severity === 'high').length;
21
+ const medium = collisionReport.collisions.filter((c) => c.severity === 'medium').length;
22
+ const contendedTargets = new Set(findContendedClaims(claims).map((c) => c.target)).size;
23
+ const readiness = high > 0 || contendedTargets > 0
24
+ ? 'conflicted'
25
+ : medium > 0
26
+ ? 'caution'
27
+ : 'clear';
28
+ const summary = [];
29
+ summary.push(`${collisionReport.worktrees.length} in-flight worktree(s).`);
30
+ if (high + medium > 0) {
31
+ summary.push(`${high + medium} collision(s): ${high} high, ${medium} medium.`);
32
+ }
33
+ else {
34
+ summary.push('No collisions across worktrees.');
35
+ }
36
+ if (contendedTargets > 0)
37
+ summary.push(`${contendedTargets} claim target(s) contended by multiple agents.`);
38
+ if (mergeRisk.hotFiles.length > 0)
39
+ summary.push(`${mergeRisk.hotFiles.length} merge hotspot file(s).`);
40
+ if (mergeRisk.integrationOrder.length > 0) {
41
+ const first = mergeRisk.integrationOrder[0];
42
+ summary.push(`Merge ${first.branch ?? first.worktree} first (lowest risk).`);
43
+ }
44
+ return {
45
+ schemaVersion: 1,
46
+ available: true,
47
+ worktreeCount: collisionReport.worktrees.length,
48
+ collisions: { total: collisionReport.collisions.length, high, medium },
49
+ claims: { total: claims.length, contendedTargets },
50
+ mergeRisk: {
51
+ hotspotCount: mergeRisk.hotFiles.length,
52
+ integrationOrder: mergeRisk.integrationOrder.map((o) => ({
53
+ worktree: o.worktree,
54
+ branch: o.branch,
55
+ riskScore: o.riskScore,
56
+ })),
57
+ },
58
+ readiness,
59
+ summary,
60
+ };
61
+ }
62
+ /** Run the full coordination read for the repo's in-flight worktrees. */
63
+ export async function computeCoordination(rootPath, options = {}) {
64
+ const [collisionReport, claims, mergeRisk] = await Promise.all([
65
+ detectCollisions(rootPath, options),
66
+ listClaims(rootPath),
67
+ computeMergeRisk(rootPath, options),
68
+ ]);
69
+ return summarizeCoordination({ collisionReport, claims, mergeRisk });
70
+ }
71
+ //# sourceMappingURL=coordination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordination.js","sourceRoot":"","sources":["../../src/core/coordination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAwB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAc,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAwB,MAAM,gBAAgB,CAAC;AAmCxE,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB,CAAC,MAA0B;IAC9D,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAEtD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;QAC/B,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,SAAS,EAAE,KAAK;YAChB,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,aAAa,EAAE,eAAe,CAAC,SAAS,CAAC,MAAM;YAC/C,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;YAC5C,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,EAAE;YACrD,SAAS,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE;YACpD,SAAS,EAAE,OAAO;YAClB,OAAO,EAAE,CAAC,eAAe,CAAC,MAAM,IAAI,2BAA2B,CAAC;SACjE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;IACpF,MAAM,MAAM,GAAG,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACxF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAExF,MAAM,SAAS,GACb,IAAI,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC;QAC9B,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,MAAM,GAAG,CAAC;YACV,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,OAAO,CAAC;IAEhB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,yBAAyB,CAAC,CAAC;IAC3E,IAAI,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,MAAM,kBAAkB,IAAI,UAAU,MAAM,UAAU,CAAC,CAAC;IACjF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,gBAAgB,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,gBAAgB,gDAAgD,CAAC,CAAC;IAC5G,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,yBAAyB,CAAC,CAAC;IACvG,IAAI,SAAS,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,uBAAuB,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,eAAe,CAAC,SAAS,CAAC,MAAM;QAC/C,UAAU,EAAE,EAAE,KAAK,EAAE,eAAe,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;QACtE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE;QAClD,SAAS,EAAE;YACT,YAAY,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM;YACvC,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACvD,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC;SACJ;QACD,SAAS;QACT,OAAO;KACR,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,UAAgC,EAAE;IAElC,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC7D,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC;QACnC,UAAU,CAAC,QAAQ,CAAC;QACpB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC;KACpC,CAAC,CAAC;IACH,OAAO,qBAAqB,CAAC,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AACvE,CAAC"}