greprag 5.44.3 → 5.45.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/dist/commands/collision-check.d.ts +113 -0
- package/dist/commands/collision-check.js +266 -0
- package/dist/commands/collision-check.js.map +1 -0
- package/dist/commands/coordinate-gate.d.ts +73 -0
- package/dist/commands/coordinate-gate.js +108 -0
- package/dist/commands/coordinate-gate.js.map +1 -0
- package/dist/commands/corpus/refresh.js +1 -1
- package/dist/commands/corpus/refresh.js.map +1 -1
- package/dist/commands/inbox-drain.d.ts +49 -0
- package/dist/commands/inbox-drain.js +163 -0
- package/dist/commands/inbox-drain.js.map +1 -0
- package/dist/commands/inbox-poll.d.ts +47 -0
- package/dist/commands/inbox-poll.js +261 -0
- package/dist/commands/inbox-poll.js.map +1 -0
- package/dist/commands/inbox-watch.js +3 -0
- package/dist/commands/inbox-watch.js.map +1 -1
- package/dist/commands/ingress-trigger.d.ts +67 -0
- package/dist/commands/ingress-trigger.js +103 -0
- package/dist/commands/ingress-trigger.js.map +1 -0
- package/dist/commands/init.js +41 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/poll-registry.d.ts +56 -0
- package/dist/commands/poll-registry.js +261 -0
- package/dist/commands/poll-registry.js.map +1 -0
- package/dist/commands/state-trigger.d.ts +66 -0
- package/dist/commands/state-trigger.js +305 -0
- package/dist/commands/state-trigger.js.map +1 -0
- package/dist/fix-trigger.d.ts +25 -5
- package/dist/fix-trigger.js +35 -11
- package/dist/fix-trigger.js.map +1 -1
- package/dist/guard.d.ts +13 -0
- package/dist/guard.js +58 -3
- package/dist/guard.js.map +1 -1
- package/dist/hook.js +226 -4
- package/dist/hook.js.map +1 -1
- package/dist/index.js +70 -1
- package/dist/index.js.map +1 -1
- package/dist/session-id.d.ts +12 -0
- package/dist/session-id.js +17 -0
- package/dist/session-id.js.map +1 -1
- package/package.json +1 -1
- package/skill/greprag/SKILL.md +4 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/** Collision schematic — detect another live session working in the SAME repo
|
|
2
|
+
* and inject a directive telling the agent to coordinate (message the peer +
|
|
3
|
+
* work in a worktree). The operator does this by hand today; this makes it a
|
|
4
|
+
* reflex. adr: docs/schematic-triggers.md, docs/stateful-injection.md
|
|
5
|
+
*
|
|
6
|
+
* WHERE IT FIRES: wired as a SessionStart hook (startup + resume + compact).
|
|
7
|
+
* Because BOTH sides run it at their own start, whichever session starts LAST
|
|
8
|
+
* detects the overlap and pings the other — mutual coverage with no polling.
|
|
9
|
+
*
|
|
10
|
+
* THE SIGNAL: `GET /v1/inbox/watchers` (the cloud registry) lists every armed
|
|
11
|
+
* watcher under the tenant as `{project_id, project_name, session_id, title,
|
|
12
|
+
* wide}`. A collision is any row with MY project (by project_id — the git-root-
|
|
13
|
+
* commit UUID, identical across worktrees of one repo — with a project_name
|
|
14
|
+
* fallback) and a DIFFERENT session id. Project matching IS the discriminator:
|
|
15
|
+
* service watchers (receptionist / desk-line / the Assistant) carry a different
|
|
16
|
+
* project_id (or none), so they never match a working session's repo and are
|
|
17
|
+
* excluded for free. (`wide` is NOT a usable filter — observed true on ordinary
|
|
18
|
+
* session-scoped watchers, not just tenant-wide ones.) Liveness here depends on
|
|
19
|
+
* the peer having an armed watcher; best-effort by construction, pairs with the
|
|
20
|
+
* asyncRewake watcher work.
|
|
21
|
+
*
|
|
22
|
+
* AI NEVER AUTO-ACTS: the hook injects a directive naming the peers; the AGENT
|
|
23
|
+
* composes and sends the contextual heads-up. The hook never sends.
|
|
24
|
+
*
|
|
25
|
+
* DEDUP: announced peers are stamped per-session at `~/.greprag/collisions/
|
|
26
|
+
* <short>.json`, so a resume/compact re-fire (or a PreToolUse re-wire) pings
|
|
27
|
+
* each peer at most once per session — not every turn. */
|
|
28
|
+
/** One row from `GET /v1/inbox/watchers` (the cloud live-session registry). */
|
|
29
|
+
export interface WatcherRow {
|
|
30
|
+
project_id: string | null;
|
|
31
|
+
project_name: string | null;
|
|
32
|
+
session_id: string | null;
|
|
33
|
+
title: string | null;
|
|
34
|
+
wide: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** A colliding peer: its 8-hex session id + the title resolved from its memory. */
|
|
37
|
+
export interface CollisionPeer {
|
|
38
|
+
short: string;
|
|
39
|
+
title: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Reduce the tenant watcher list to the colliding peers in MY repo. PURE. */
|
|
42
|
+
export declare function detectCollisions(myShort: string, myProjectId: string | null, myProjectName: string | null, watchers: WatcherRow[]): CollisionPeer[];
|
|
43
|
+
/** Split detected peers into the ones not yet announced this session (`fresh`)
|
|
44
|
+
* and the new announced set (`union`). PURE — the dedup contract. */
|
|
45
|
+
export declare function dedupePeers(peers: CollisionPeer[], announced: string[]): {
|
|
46
|
+
fresh: CollisionPeer[];
|
|
47
|
+
union: string[];
|
|
48
|
+
};
|
|
49
|
+
/** The LOUD directive — same `additionalContext` shape as the arm directive,
|
|
50
|
+
* naming each peer + instructing message-then-worktree. PURE. */
|
|
51
|
+
export declare function buildCollisionDirective(peers: CollisionPeer[], myShort: string, alias: string | null): string;
|
|
52
|
+
/** A live session working in ANOTHER repo — the QUIET whisper roster entry. */
|
|
53
|
+
export interface RosterSession {
|
|
54
|
+
short: string;
|
|
55
|
+
title: string | null;
|
|
56
|
+
projectName: string | null;
|
|
57
|
+
}
|
|
58
|
+
/** Reduce the watcher list to OTHER live sessions that are NOT in my repo
|
|
59
|
+
* (cross-repo). Excludes self, same-repo collisions (those get the LOUD
|
|
60
|
+
* directive), and rows with no session id or no project_name (service watchers
|
|
61
|
+
* — receptionist / desk-line / Assistant — are unnamed or differently-anchored,
|
|
62
|
+
* so they fall out without a role special-case). PURE. */
|
|
63
|
+
export declare function detectOtherSessions(myShort: string, myProjectId: string | null, myProjectName: string | null, watchers: WatcherRow[]): RosterSession[];
|
|
64
|
+
/** The QUIET whisper — a single FYI line naming other live sessions and the repo
|
|
65
|
+
* each is in. No directive (cross-repo can't collide on shared files), just
|
|
66
|
+
* awareness. PURE. null for an empty roster. */
|
|
67
|
+
export declare function buildRosterWhisper(sessions: RosterSession[]): string | null;
|
|
68
|
+
/** Only-on-change gate for the whisper: emit iff the cross-repo session SET
|
|
69
|
+
* differs from the last-emitted roster. Returns the sorted current set so the
|
|
70
|
+
* caller can persist it. PURE. */
|
|
71
|
+
export declare function dedupeRoster(sessions: RosterSession[], lastRoster: string[]): {
|
|
72
|
+
changed: boolean;
|
|
73
|
+
shorts: string[];
|
|
74
|
+
};
|
|
75
|
+
/** Per-session collision state, persisted at ~/.greprag/collisions/<short>.json.
|
|
76
|
+
* `announced` = same-repo peers already given the LOUD directive (monotonic add,
|
|
77
|
+
* per-session dedup). `roster` = the last-emitted set of cross-repo session
|
|
78
|
+
* shorts (a snapshot, for the QUIET whisper's only-on-change gate). One file,
|
|
79
|
+
* one read, one write per check. */
|
|
80
|
+
export interface CollisionState {
|
|
81
|
+
announced: string[];
|
|
82
|
+
roster: string[];
|
|
83
|
+
}
|
|
84
|
+
/** Read both dedup ledgers. Empty state on any error (fail-open: at worst a peer
|
|
85
|
+
* is re-announced / the roster re-whispered once). */
|
|
86
|
+
export declare function readCollisionState(short: string): CollisionState;
|
|
87
|
+
/** Write both ledgers in one shot. Best-effort — a failed write only means a
|
|
88
|
+
* re-announce / re-whisper next fire. */
|
|
89
|
+
export declare function writeCollisionState(short: string, state: CollisionState): void;
|
|
90
|
+
/** Back-compat shim — same-repo announced ledger only. */
|
|
91
|
+
export declare function readAnnounced(short: string): string[];
|
|
92
|
+
/** Back-compat shim — merges into existing state so the roster ledger survives. */
|
|
93
|
+
export declare function writeAnnounced(short: string, announced: string[]): void;
|
|
94
|
+
/** Fetch the tenant's live watcher registry. Best-effort: any failure (network,
|
|
95
|
+
* non-200, malformed) returns [] so a collision check never blocks or throws. */
|
|
96
|
+
export declare function fetchTenantWatchers(apiUrl: string, apiKey: string): Promise<WatcherRow[]>;
|
|
97
|
+
export interface CollisionCheckOptions {
|
|
98
|
+
short: string;
|
|
99
|
+
projectId: string | null;
|
|
100
|
+
projectName: string | null;
|
|
101
|
+
apiUrl: string;
|
|
102
|
+
apiKey: string;
|
|
103
|
+
alias: string | null;
|
|
104
|
+
}
|
|
105
|
+
/** Orchestrate one collision check. Returns the text to inject, or null. Combines
|
|
106
|
+
* TWO independent signals over a SINGLE watcher read:
|
|
107
|
+
* · LOUD — same-repo peers (a real collision risk) → coordinate directive,
|
|
108
|
+
* per-session dedup (each peer announced at most once).
|
|
109
|
+
* · QUIET — other live sessions in OTHER repos → one-line FYI roster, emitted
|
|
110
|
+
* only when the set changes.
|
|
111
|
+
* One state read + at most one state write. The hook wrapper resolves cfg/
|
|
112
|
+
* anchor/alias and writes the returned text as additionalContext. */
|
|
113
|
+
export declare function runCollisionCheck(opts: CollisionCheckOptions): Promise<string | null>;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Collision schematic — detect another live session working in the SAME repo
|
|
3
|
+
* and inject a directive telling the agent to coordinate (message the peer +
|
|
4
|
+
* work in a worktree). The operator does this by hand today; this makes it a
|
|
5
|
+
* reflex. adr: docs/schematic-triggers.md, docs/stateful-injection.md
|
|
6
|
+
*
|
|
7
|
+
* WHERE IT FIRES: wired as a SessionStart hook (startup + resume + compact).
|
|
8
|
+
* Because BOTH sides run it at their own start, whichever session starts LAST
|
|
9
|
+
* detects the overlap and pings the other — mutual coverage with no polling.
|
|
10
|
+
*
|
|
11
|
+
* THE SIGNAL: `GET /v1/inbox/watchers` (the cloud registry) lists every armed
|
|
12
|
+
* watcher under the tenant as `{project_id, project_name, session_id, title,
|
|
13
|
+
* wide}`. A collision is any row with MY project (by project_id — the git-root-
|
|
14
|
+
* commit UUID, identical across worktrees of one repo — with a project_name
|
|
15
|
+
* fallback) and a DIFFERENT session id. Project matching IS the discriminator:
|
|
16
|
+
* service watchers (receptionist / desk-line / the Assistant) carry a different
|
|
17
|
+
* project_id (or none), so they never match a working session's repo and are
|
|
18
|
+
* excluded for free. (`wide` is NOT a usable filter — observed true on ordinary
|
|
19
|
+
* session-scoped watchers, not just tenant-wide ones.) Liveness here depends on
|
|
20
|
+
* the peer having an armed watcher; best-effort by construction, pairs with the
|
|
21
|
+
* asyncRewake watcher work.
|
|
22
|
+
*
|
|
23
|
+
* AI NEVER AUTO-ACTS: the hook injects a directive naming the peers; the AGENT
|
|
24
|
+
* composes and sends the contextual heads-up. The hook never sends.
|
|
25
|
+
*
|
|
26
|
+
* DEDUP: announced peers are stamped per-session at `~/.greprag/collisions/
|
|
27
|
+
* <short>.json`, so a resume/compact re-fire (or a PreToolUse re-wire) pings
|
|
28
|
+
* each peer at most once per session — not every turn. */
|
|
29
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
33
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperty(o, k2, desc);
|
|
36
|
+
}) : (function(o, m, k, k2) {
|
|
37
|
+
if (k2 === undefined) k2 = k;
|
|
38
|
+
o[k2] = m[k];
|
|
39
|
+
}));
|
|
40
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
41
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
42
|
+
}) : function(o, v) {
|
|
43
|
+
o["default"] = v;
|
|
44
|
+
});
|
|
45
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
46
|
+
var ownKeys = function(o) {
|
|
47
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
48
|
+
var ar = [];
|
|
49
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
50
|
+
return ar;
|
|
51
|
+
};
|
|
52
|
+
return ownKeys(o);
|
|
53
|
+
};
|
|
54
|
+
return function (mod) {
|
|
55
|
+
if (mod && mod.__esModule) return mod;
|
|
56
|
+
var result = {};
|
|
57
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
58
|
+
__setModuleDefault(result, mod);
|
|
59
|
+
return result;
|
|
60
|
+
};
|
|
61
|
+
})();
|
|
62
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
63
|
+
exports.detectCollisions = detectCollisions;
|
|
64
|
+
exports.dedupePeers = dedupePeers;
|
|
65
|
+
exports.buildCollisionDirective = buildCollisionDirective;
|
|
66
|
+
exports.detectOtherSessions = detectOtherSessions;
|
|
67
|
+
exports.buildRosterWhisper = buildRosterWhisper;
|
|
68
|
+
exports.dedupeRoster = dedupeRoster;
|
|
69
|
+
exports.readCollisionState = readCollisionState;
|
|
70
|
+
exports.writeCollisionState = writeCollisionState;
|
|
71
|
+
exports.readAnnounced = readAnnounced;
|
|
72
|
+
exports.writeAnnounced = writeAnnounced;
|
|
73
|
+
exports.fetchTenantWatchers = fetchTenantWatchers;
|
|
74
|
+
exports.runCollisionCheck = runCollisionCheck;
|
|
75
|
+
const fs = __importStar(require("fs"));
|
|
76
|
+
const path = __importStar(require("path"));
|
|
77
|
+
const session_id_1 = require("../session-id");
|
|
78
|
+
/** True iff a watcher row is another live session in MY repo. PURE + testable —
|
|
79
|
+
* the entire detection contract lives here.
|
|
80
|
+
* · self is excluded by the 8-hex compare (both sides truncated).
|
|
81
|
+
* · match on project_id (the stable git-root-commit UUID, identical across
|
|
82
|
+
* worktrees of the same repo) with a project_name fallback for rows whose
|
|
83
|
+
* id the cloud could not resolve. Service watchers (receptionist / desk-line
|
|
84
|
+
* / Assistant) carry a different project_id (or none), so they fail the match
|
|
85
|
+
* and are excluded without any role/`wide` special-case. */
|
|
86
|
+
function isCollision(myShort, myProjectId, myProjectName, w) {
|
|
87
|
+
const peerShort = (0, session_id_1.truncateSessionId)(w.session_id);
|
|
88
|
+
if (!peerShort || peerShort === myShort)
|
|
89
|
+
return false;
|
|
90
|
+
const idMatch = !!(myProjectId && w.project_id && w.project_id === myProjectId);
|
|
91
|
+
const nameMatch = !!(myProjectName && w.project_name &&
|
|
92
|
+
w.project_name.toLowerCase() === myProjectName.toLowerCase());
|
|
93
|
+
return idMatch || nameMatch;
|
|
94
|
+
}
|
|
95
|
+
/** Reduce the tenant watcher list to the colliding peers in MY repo. PURE. */
|
|
96
|
+
function detectCollisions(myShort, myProjectId, myProjectName, watchers) {
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
const peers = [];
|
|
99
|
+
for (const w of watchers) {
|
|
100
|
+
if (!isCollision(myShort, myProjectId, myProjectName, w))
|
|
101
|
+
continue;
|
|
102
|
+
const short = (0, session_id_1.truncateSessionId)(w.session_id);
|
|
103
|
+
if (seen.has(short))
|
|
104
|
+
continue; // one watcher row per session is plenty
|
|
105
|
+
seen.add(short);
|
|
106
|
+
peers.push({ short, title: w.title });
|
|
107
|
+
}
|
|
108
|
+
return peers;
|
|
109
|
+
}
|
|
110
|
+
/** Split detected peers into the ones not yet announced this session (`fresh`)
|
|
111
|
+
* and the new announced set (`union`). PURE — the dedup contract. */
|
|
112
|
+
function dedupePeers(peers, announced) {
|
|
113
|
+
const known = new Set(announced);
|
|
114
|
+
const fresh = peers.filter(p => !known.has(p.short));
|
|
115
|
+
const union = Array.from(new Set([...announced, ...peers.map(p => p.short)]));
|
|
116
|
+
return { fresh, union };
|
|
117
|
+
}
|
|
118
|
+
/** The LOUD directive — same `additionalContext` shape as the arm directive,
|
|
119
|
+
* naming each peer + instructing message-then-worktree. PURE. */
|
|
120
|
+
function buildCollisionDirective(peers, myShort, alias) {
|
|
121
|
+
const handle = alias || '<handle>';
|
|
122
|
+
const lines = peers.map(p => ` · ${p.short}${p.title ? ` — "${p.title}"` : ''}`);
|
|
123
|
+
const plural = peers.length === 1 ? '' : 's';
|
|
124
|
+
return (`COLLISION DETECTED — ${peers.length} other live session${plural} working in this same repo right now:\n`
|
|
125
|
+
+ lines.join('\n') + '\n'
|
|
126
|
+
+ `Coordinate BEFORE touching shared files: (1) message each peer now with a contextual heads-up — `
|
|
127
|
+
+ `\`greprag send "…what you're about to touch…" --to ${handle}@greprag.com/<their-8hex> --from-session ${myShort}\` `
|
|
128
|
+
+ `(YOU compose and send it — this is a notice, not an auto-send); `
|
|
129
|
+
+ `(2) do your code work in a worktree on its own branch (\`git worktree add .claude/worktrees/<slug> -b <branch>\`) `
|
|
130
|
+
+ `and merge to main only on the operator's word — never edit shared main concurrently.`);
|
|
131
|
+
}
|
|
132
|
+
/** Reduce the watcher list to OTHER live sessions that are NOT in my repo
|
|
133
|
+
* (cross-repo). Excludes self, same-repo collisions (those get the LOUD
|
|
134
|
+
* directive), and rows with no session id or no project_name (service watchers
|
|
135
|
+
* — receptionist / desk-line / Assistant — are unnamed or differently-anchored,
|
|
136
|
+
* so they fall out without a role special-case). PURE. */
|
|
137
|
+
function detectOtherSessions(myShort, myProjectId, myProjectName, watchers) {
|
|
138
|
+
const seen = new Set();
|
|
139
|
+
const out = [];
|
|
140
|
+
for (const w of watchers) {
|
|
141
|
+
const short = (0, session_id_1.truncateSessionId)(w.session_id);
|
|
142
|
+
if (!short || short === myShort)
|
|
143
|
+
continue;
|
|
144
|
+
if (isCollision(myShort, myProjectId, myProjectName, w))
|
|
145
|
+
continue; // same-repo → LOUD
|
|
146
|
+
if (!w.project_name)
|
|
147
|
+
continue; // unnamed/service → skip
|
|
148
|
+
if (seen.has(short))
|
|
149
|
+
continue;
|
|
150
|
+
seen.add(short);
|
|
151
|
+
out.push({ short, title: w.title, projectName: w.project_name });
|
|
152
|
+
}
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
/** The QUIET whisper — a single FYI line naming other live sessions and the repo
|
|
156
|
+
* each is in. No directive (cross-repo can't collide on shared files), just
|
|
157
|
+
* awareness. PURE. null for an empty roster. */
|
|
158
|
+
function buildRosterWhisper(sessions) {
|
|
159
|
+
if (sessions.length === 0)
|
|
160
|
+
return null;
|
|
161
|
+
const parts = sessions.map(s => `${s.short}@${s.projectName}${s.title ? ` ("${s.title}")` : ''}`);
|
|
162
|
+
const plural = sessions.length === 1 ? '' : 's';
|
|
163
|
+
return `[Live elsewhere — ${sessions.length} other session${plural} active in your tenant `
|
|
164
|
+
+ `(cross-repo, FYI only): ${parts.join(' · ')}]`;
|
|
165
|
+
}
|
|
166
|
+
/** Only-on-change gate for the whisper: emit iff the cross-repo session SET
|
|
167
|
+
* differs from the last-emitted roster. Returns the sorted current set so the
|
|
168
|
+
* caller can persist it. PURE. */
|
|
169
|
+
function dedupeRoster(sessions, lastRoster) {
|
|
170
|
+
const shorts = sessions.map(s => s.short).sort();
|
|
171
|
+
const prev = [...lastRoster].sort();
|
|
172
|
+
const changed = shorts.length !== prev.length || shorts.some((s, i) => s !== prev[i]);
|
|
173
|
+
return { changed, shorts };
|
|
174
|
+
}
|
|
175
|
+
// ---- IO (best-effort; never throws into the hook) -------------------------
|
|
176
|
+
function grepragHome() {
|
|
177
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
178
|
+
return home ? path.join(home, '.greprag') : null;
|
|
179
|
+
}
|
|
180
|
+
function announcedPath(short) {
|
|
181
|
+
const h = grepragHome();
|
|
182
|
+
return h ? path.join(h, 'collisions', `${short}.json`) : null;
|
|
183
|
+
}
|
|
184
|
+
function asStringArray(v) {
|
|
185
|
+
return Array.isArray(v) ? v.filter((s) => typeof s === 'string') : [];
|
|
186
|
+
}
|
|
187
|
+
/** Read both dedup ledgers. Empty state on any error (fail-open: at worst a peer
|
|
188
|
+
* is re-announced / the roster re-whispered once). */
|
|
189
|
+
function readCollisionState(short) {
|
|
190
|
+
try {
|
|
191
|
+
const p = announcedPath(short);
|
|
192
|
+
if (!p)
|
|
193
|
+
return { announced: [], roster: [] };
|
|
194
|
+
const parsed = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
195
|
+
return { announced: asStringArray(parsed?.announced), roster: asStringArray(parsed?.roster) };
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return { announced: [], roster: [] };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/** Write both ledgers in one shot. Best-effort — a failed write only means a
|
|
202
|
+
* re-announce / re-whisper next fire. */
|
|
203
|
+
function writeCollisionState(short, state) {
|
|
204
|
+
try {
|
|
205
|
+
const p = announcedPath(short);
|
|
206
|
+
if (!p)
|
|
207
|
+
return;
|
|
208
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
209
|
+
fs.writeFileSync(p, JSON.stringify({ announced: state.announced, roster: state.roster }));
|
|
210
|
+
}
|
|
211
|
+
catch { /* best-effort */ }
|
|
212
|
+
}
|
|
213
|
+
/** Back-compat shim — same-repo announced ledger only. */
|
|
214
|
+
function readAnnounced(short) {
|
|
215
|
+
return readCollisionState(short).announced;
|
|
216
|
+
}
|
|
217
|
+
/** Back-compat shim — merges into existing state so the roster ledger survives. */
|
|
218
|
+
function writeAnnounced(short, announced) {
|
|
219
|
+
writeCollisionState(short, { announced, roster: readCollisionState(short).roster });
|
|
220
|
+
}
|
|
221
|
+
/** Fetch the tenant's live watcher registry. Best-effort: any failure (network,
|
|
222
|
+
* non-200, malformed) returns [] so a collision check never blocks or throws. */
|
|
223
|
+
async function fetchTenantWatchers(apiUrl, apiKey) {
|
|
224
|
+
try {
|
|
225
|
+
const url = `${apiUrl.replace(/\/+$/, '')}/v1/inbox/watchers`;
|
|
226
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
227
|
+
if (!res.ok)
|
|
228
|
+
return [];
|
|
229
|
+
const data = await res.json();
|
|
230
|
+
return Array.isArray(data?.watchers) ? data.watchers : [];
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** Orchestrate one collision check. Returns the text to inject, or null. Combines
|
|
237
|
+
* TWO independent signals over a SINGLE watcher read:
|
|
238
|
+
* · LOUD — same-repo peers (a real collision risk) → coordinate directive,
|
|
239
|
+
* per-session dedup (each peer announced at most once).
|
|
240
|
+
* · QUIET — other live sessions in OTHER repos → one-line FYI roster, emitted
|
|
241
|
+
* only when the set changes.
|
|
242
|
+
* One state read + at most one state write. The hook wrapper resolves cfg/
|
|
243
|
+
* anchor/alias and writes the returned text as additionalContext. */
|
|
244
|
+
async function runCollisionCheck(opts) {
|
|
245
|
+
const watchers = await fetchTenantWatchers(opts.apiUrl, opts.apiKey);
|
|
246
|
+
if (watchers.length === 0)
|
|
247
|
+
return null;
|
|
248
|
+
const state = readCollisionState(opts.short);
|
|
249
|
+
// LOUD: same-repo collisions, deduped per session.
|
|
250
|
+
const peers = detectCollisions(opts.short, opts.projectId, opts.projectName, watchers);
|
|
251
|
+
const { fresh, union } = dedupePeers(peers, state.announced);
|
|
252
|
+
const loud = fresh.length > 0
|
|
253
|
+
? buildCollisionDirective(fresh, opts.short, opts.alias) : null;
|
|
254
|
+
// QUIET: cross-repo roster, emitted only on change.
|
|
255
|
+
const others = detectOtherSessions(opts.short, opts.projectId, opts.projectName, watchers);
|
|
256
|
+
const { changed, shorts } = dedupeRoster(others, state.roster);
|
|
257
|
+
const quiet = changed ? buildRosterWhisper(others) : null;
|
|
258
|
+
// Single write — persist whenever either ledger moved (incl. roster → empty,
|
|
259
|
+
// so a later re-appearance re-whispers).
|
|
260
|
+
if (fresh.length > 0 || changed) {
|
|
261
|
+
writeCollisionState(opts.short, { announced: union, roster: shorts });
|
|
262
|
+
}
|
|
263
|
+
const parts = [loud, quiet].filter((p) => !!p);
|
|
264
|
+
return parts.length > 0 ? parts.join('\n') : null;
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=collision-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collision-check.js","sourceRoot":"","sources":["../../src/commands/collision-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Coordinate-GATE — the high-value half of the cross-session coordination reflex.
|
|
2
|
+
* Fires at the moment of a risky SHARED-STATE action (git merge / push / deploy)
|
|
3
|
+
* and, if another live session is working in THIS repo, compels the agent to
|
|
4
|
+
* coordinate with that peer BEFORE the irreversible action runs. Automates the
|
|
5
|
+
* manual "notice the peer, message them, then merge" handshake.
|
|
6
|
+
*
|
|
7
|
+
* SEAM (forward-compat — agreed with ec71d875/36ef8cb8): the EVAL+message
|
|
8
|
+
* (runCoordinateGate) is decoupled from the trigger SOURCE. The PreToolUse
|
|
9
|
+
* adapter (triggerFromPreToolUse) is the only piece that knows the tool-call
|
|
10
|
+
* shape; it produces a source-agnostic CoordinateTrigger. The eval does a FRESH
|
|
11
|
+
* watcher read and builds the directive without ever seeing the source. The
|
|
12
|
+
* ddb7dcc8 ingress-trigger bridge will add a SECOND source (message-ingress /
|
|
13
|
+
* stress-threshold / registry-change) that produces its own CoordinateTrigger
|
|
14
|
+
* and calls this same eval — purely additive, no refactor of the gate.
|
|
15
|
+
*
|
|
16
|
+
* WHY NOT A guard.ts MATCHSET RULE: the matchset dispatcher is local-only/pure
|
|
17
|
+
* (no network on the hot path — the D5 "ad-blocker" model) and injects STATIC
|
|
18
|
+
* rule text. This gate needs a FRESH `inbox watchers` network read at fire time
|
|
19
|
+
* (a stale roster at merge is the exact failure it prevents), which a static
|
|
20
|
+
* matchset cannot express. So it is a hand-wired PreToolUse hook like
|
|
21
|
+
* collision-check — the documented fallback in the chip spec. The bridge's
|
|
22
|
+
* shared eval will likewise need this off-hot-path read, so this module is its
|
|
23
|
+
* home too. docs/collision-schematic.md, docs/harness-control-point-matrix.md
|
|
24
|
+
*
|
|
25
|
+
* NO DEDUP: every fire does a fresh read. Unlike the SessionStart roster (which
|
|
26
|
+
* dedups to stay quiet), the merge gate must reflect live truth each time.
|
|
27
|
+
*
|
|
28
|
+
* EFFECT is the adapter's choice, not the eval's: the PreToolUse wrapper (in
|
|
29
|
+
* hook.ts) raises a permission `ask` — a true pause before the merge, with the
|
|
30
|
+
* fresh roster as the reason. An ingress-source wrapper would inject instead.
|
|
31
|
+
* The eval below only produces the message.
|
|
32
|
+
*
|
|
33
|
+
* Shared-file Write was CONSIDERED (chip spec) but deferred: classifying a
|
|
34
|
+
* write as "shared" is ambiguous, and a fresh network read on every Write/Edit
|
|
35
|
+
* is too costly/noisy for the value — merge/push/deploy is where irreversible
|
|
36
|
+
* shared-state mutation actually happens. The eval is ready for a future Write
|
|
37
|
+
* adapter; only a new triggerFrom* + a `Write|Edit` matcher would be needed. */
|
|
38
|
+
import { CollisionPeer } from './collision-check';
|
|
39
|
+
/** A source-agnostic coordination trigger — WHY we are checking peers right now.
|
|
40
|
+
* Produced by a trigger adapter (PreToolUse today; the ingress bridge later);
|
|
41
|
+
* the eval never sees the source. */
|
|
42
|
+
export interface CoordinateTrigger {
|
|
43
|
+
kind: 'merge' | 'push' | 'deploy';
|
|
44
|
+
/** The about-to-happen action, e.g. "git push", "wrangler deploy". */
|
|
45
|
+
label: string;
|
|
46
|
+
}
|
|
47
|
+
/** Classify a Bash command into a risky-action trigger, or null. PURE. Matches
|
|
48
|
+
* the FIRST risky segment (a chained command fires on whichever risky verb
|
|
49
|
+
* appears first). */
|
|
50
|
+
export declare function classifyRiskyCommand(command: string): CoordinateTrigger | null;
|
|
51
|
+
/** PreToolUse adapter: extract a CoordinateTrigger from a tool call, or null.
|
|
52
|
+
* SPECIFIC to the PreToolUse event shape — the only source-aware piece. Only
|
|
53
|
+
* Bash calls carry a risky command; everything else returns null (cheap: the
|
|
54
|
+
* hook never reaches the network for a non-risky call). */
|
|
55
|
+
export declare function triggerFromPreToolUse(toolName: string, toolInput: Record<string, unknown>): CoordinateTrigger | null;
|
|
56
|
+
/** The LOUD coordinate directive — names the action + the live same-repo peers
|
|
57
|
+
* and tells the agent to message them BEFORE proceeding. PURE, source-agnostic
|
|
58
|
+
* (takes a CoordinateTrigger, not a PreToolUse event). */
|
|
59
|
+
export declare function buildCoordinateDirective(trigger: CoordinateTrigger, peers: CollisionPeer[], myShort: string, alias: string | null): string;
|
|
60
|
+
export interface CoordinateGateOptions {
|
|
61
|
+
short: string;
|
|
62
|
+
projectId: string | null;
|
|
63
|
+
projectName: string | null;
|
|
64
|
+
apiUrl: string;
|
|
65
|
+
apiKey: string;
|
|
66
|
+
alias: string | null;
|
|
67
|
+
}
|
|
68
|
+
/** Source-agnostic eval+message. Given a trigger from ANY source, do a FRESH
|
|
69
|
+
* watcher read, detect same-repo peers, and return the LOUD directive — or null
|
|
70
|
+
* if no peer is live in this repo. NO dedup, NO local state: a fresh read every
|
|
71
|
+
* call. Best-effort: any failure (network, unanchored) → null (fail-open, the
|
|
72
|
+
* action proceeds ungated). */
|
|
73
|
+
export declare function runCoordinateGate(trigger: CoordinateTrigger, opts: CoordinateGateOptions): Promise<string | null>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/** Coordinate-GATE — the high-value half of the cross-session coordination reflex.
|
|
3
|
+
* Fires at the moment of a risky SHARED-STATE action (git merge / push / deploy)
|
|
4
|
+
* and, if another live session is working in THIS repo, compels the agent to
|
|
5
|
+
* coordinate with that peer BEFORE the irreversible action runs. Automates the
|
|
6
|
+
* manual "notice the peer, message them, then merge" handshake.
|
|
7
|
+
*
|
|
8
|
+
* SEAM (forward-compat — agreed with ec71d875/36ef8cb8): the EVAL+message
|
|
9
|
+
* (runCoordinateGate) is decoupled from the trigger SOURCE. The PreToolUse
|
|
10
|
+
* adapter (triggerFromPreToolUse) is the only piece that knows the tool-call
|
|
11
|
+
* shape; it produces a source-agnostic CoordinateTrigger. The eval does a FRESH
|
|
12
|
+
* watcher read and builds the directive without ever seeing the source. The
|
|
13
|
+
* ddb7dcc8 ingress-trigger bridge will add a SECOND source (message-ingress /
|
|
14
|
+
* stress-threshold / registry-change) that produces its own CoordinateTrigger
|
|
15
|
+
* and calls this same eval — purely additive, no refactor of the gate.
|
|
16
|
+
*
|
|
17
|
+
* WHY NOT A guard.ts MATCHSET RULE: the matchset dispatcher is local-only/pure
|
|
18
|
+
* (no network on the hot path — the D5 "ad-blocker" model) and injects STATIC
|
|
19
|
+
* rule text. This gate needs a FRESH `inbox watchers` network read at fire time
|
|
20
|
+
* (a stale roster at merge is the exact failure it prevents), which a static
|
|
21
|
+
* matchset cannot express. So it is a hand-wired PreToolUse hook like
|
|
22
|
+
* collision-check — the documented fallback in the chip spec. The bridge's
|
|
23
|
+
* shared eval will likewise need this off-hot-path read, so this module is its
|
|
24
|
+
* home too. docs/collision-schematic.md, docs/harness-control-point-matrix.md
|
|
25
|
+
*
|
|
26
|
+
* NO DEDUP: every fire does a fresh read. Unlike the SessionStart roster (which
|
|
27
|
+
* dedups to stay quiet), the merge gate must reflect live truth each time.
|
|
28
|
+
*
|
|
29
|
+
* EFFECT is the adapter's choice, not the eval's: the PreToolUse wrapper (in
|
|
30
|
+
* hook.ts) raises a permission `ask` — a true pause before the merge, with the
|
|
31
|
+
* fresh roster as the reason. An ingress-source wrapper would inject instead.
|
|
32
|
+
* The eval below only produces the message.
|
|
33
|
+
*
|
|
34
|
+
* Shared-file Write was CONSIDERED (chip spec) but deferred: classifying a
|
|
35
|
+
* write as "shared" is ambiguous, and a fresh network read on every Write/Edit
|
|
36
|
+
* is too costly/noisy for the value — merge/push/deploy is where irreversible
|
|
37
|
+
* shared-state mutation actually happens. The eval is ready for a future Write
|
|
38
|
+
* adapter; only a new triggerFrom* + a `Write|Edit` matcher would be needed. */
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.classifyRiskyCommand = classifyRiskyCommand;
|
|
41
|
+
exports.triggerFromPreToolUse = triggerFromPreToolUse;
|
|
42
|
+
exports.buildCoordinateDirective = buildCoordinateDirective;
|
|
43
|
+
exports.runCoordinateGate = runCoordinateGate;
|
|
44
|
+
const collision_check_1 = require("./collision-check");
|
|
45
|
+
/** Risky shared-state command signatures. Each segment of a (possibly chained)
|
|
46
|
+
* Bash command is tested against these. SPECIFIC to the Bash/PreToolUse source. */
|
|
47
|
+
const RISKY_PATTERNS = [
|
|
48
|
+
{ kind: 'merge', label: 'git merge', re: /^git\s+merge\b/ },
|
|
49
|
+
{ kind: 'push', label: 'git push', re: /^git\s+push\b/ },
|
|
50
|
+
{ kind: 'deploy', label: 'wrangler deploy', re: /^(?:npx\s+)?wrangler\s+deploy\b/ },
|
|
51
|
+
{ kind: 'deploy', label: 'npm run deploy', re: /^npm\s+run\s+deploy\b/ },
|
|
52
|
+
{ kind: 'deploy', label: 'npm publish', re: /^npm\s+publish\b/ },
|
|
53
|
+
{ kind: 'deploy', label: 'gh release create', re: /^gh\s+release\s+create\b/ },
|
|
54
|
+
];
|
|
55
|
+
/** Split a shell command on separators so `cd x && git push` is caught. */
|
|
56
|
+
function commandSegments(command) {
|
|
57
|
+
return command.split(/&&|\|\||;|\n|\|/).map(s => s.trim()).filter(Boolean);
|
|
58
|
+
}
|
|
59
|
+
/** Classify a Bash command into a risky-action trigger, or null. PURE. Matches
|
|
60
|
+
* the FIRST risky segment (a chained command fires on whichever risky verb
|
|
61
|
+
* appears first). */
|
|
62
|
+
function classifyRiskyCommand(command) {
|
|
63
|
+
if (!command)
|
|
64
|
+
return null;
|
|
65
|
+
for (const seg of commandSegments(command)) {
|
|
66
|
+
for (const p of RISKY_PATTERNS) {
|
|
67
|
+
if (p.re.test(seg))
|
|
68
|
+
return { kind: p.kind, label: p.label };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/** PreToolUse adapter: extract a CoordinateTrigger from a tool call, or null.
|
|
74
|
+
* SPECIFIC to the PreToolUse event shape — the only source-aware piece. Only
|
|
75
|
+
* Bash calls carry a risky command; everything else returns null (cheap: the
|
|
76
|
+
* hook never reaches the network for a non-risky call). */
|
|
77
|
+
function triggerFromPreToolUse(toolName, toolInput) {
|
|
78
|
+
if (toolName !== 'Bash')
|
|
79
|
+
return null;
|
|
80
|
+
const command = typeof toolInput.command === 'string' ? toolInput.command : '';
|
|
81
|
+
return classifyRiskyCommand(command);
|
|
82
|
+
}
|
|
83
|
+
/** The LOUD coordinate directive — names the action + the live same-repo peers
|
|
84
|
+
* and tells the agent to message them BEFORE proceeding. PURE, source-agnostic
|
|
85
|
+
* (takes a CoordinateTrigger, not a PreToolUse event). */
|
|
86
|
+
function buildCoordinateDirective(trigger, peers, myShort, alias) {
|
|
87
|
+
const handle = alias || '<handle>';
|
|
88
|
+
const plural = peers.length === 1 ? '' : 's';
|
|
89
|
+
const list = peers.map(p => p.short).join(', ');
|
|
90
|
+
return (`COORDINATE before ${trigger.label}: ${peers.length} peer${plural} live in this repo (${list}). `
|
|
91
|
+
+ `Ping before proceeding — greprag send "heads up, about to ${trigger.label}" `
|
|
92
|
+
+ `--to ${handle}@greprag.com/<8hex> --from-session ${myShort}`);
|
|
93
|
+
}
|
|
94
|
+
/** Source-agnostic eval+message. Given a trigger from ANY source, do a FRESH
|
|
95
|
+
* watcher read, detect same-repo peers, and return the LOUD directive — or null
|
|
96
|
+
* if no peer is live in this repo. NO dedup, NO local state: a fresh read every
|
|
97
|
+
* call. Best-effort: any failure (network, unanchored) → null (fail-open, the
|
|
98
|
+
* action proceeds ungated). */
|
|
99
|
+
async function runCoordinateGate(trigger, opts) {
|
|
100
|
+
const watchers = await (0, collision_check_1.fetchTenantWatchers)(opts.apiUrl, opts.apiKey);
|
|
101
|
+
if (watchers.length === 0)
|
|
102
|
+
return null;
|
|
103
|
+
const peers = (0, collision_check_1.detectCollisions)(opts.short, opts.projectId, opts.projectName, watchers);
|
|
104
|
+
if (peers.length === 0)
|
|
105
|
+
return null;
|
|
106
|
+
return buildCoordinateDirective(trigger, peers, opts.short, opts.alias);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=coordinate-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinate-gate.js","sourceRoot":"","sources":["../../src/commands/coordinate-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -107,7 +107,7 @@ async function auditCmd(args) {
|
|
|
107
107
|
console.log(`\n${store.name} · refresh audits`);
|
|
108
108
|
const audits = res.audits || [];
|
|
109
109
|
if (audits.length === 0) {
|
|
110
|
-
console.log(' No
|
|
110
|
+
console.log(' No change-driven refreshes recorded since last ingest (audits are written only when a refresh detects a change).');
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
113
|
for (const a of audits) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/commands/corpus/refresh.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/commands/corpus/refresh.ts"],"names":[],"mappings":";AAAA;;;;;;;;gFAQgF;;AAoEhF,gCAiCC;AAED,gCAyCC;AAED,4BAoCC;AApLD,qCAEkB;AAgEX,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,GAAG,GAAG,IAAA,kBAAS,GAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,IAAA,2BAAkB,GAAE,CAAC;IAEtC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,8IAA8I,CAAC,CAAC;QAC9J,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAY,EAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,IAAA,gBAAO,EACvB,GAAG,GAAG,CAAC,MAAM,cAAc,KAAK,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAC9D,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IAC3E,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;IAErB,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,CAAC,YAAY;QAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;IAClE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,CAAC,YAAY,GAAG,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,UAAU,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,gBAAgB,SAAS,CAAC,CAAC;QACrF,IAAI,CAAC,CAAC,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAE3C,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,sJAAsJ,CAAC,CAAC;IACtK,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,UAAU,CAAC,IAAc;IAC7C,MAAM,GAAG,GAAG,IAAA,kBAAS,GAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,IAAA,2BAAkB,GAAE,CAAC;IAEtC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,wIAAwI,CAAC,CAAC;QACxJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAY,EAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAE9D,MAAM,GAAG,GAAG,MAAM,IAAA,eAAM,EACtB,GAAG,GAAG,CAAC,MAAM,cAAc,KAAK,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,CAC1D,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,gBAAgB,CAAC,CAAC;IAE5D,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,YAAY,CAAC,CAAC;IACzC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;QACnF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,GAAG,IAAI,0BAA0B,EAAE,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3C,IAAI,EAAE,CAAC,iBAAiB;QAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAChF,IAAI,EAAE,CAAC,YAAY;QAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;IAC3H,IAAI,EAAE,CAAC,mBAAmB,IAAI,EAAE,CAAC,mBAAmB,GAAG,CAAC,EAAE,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,mBAAmB,4BAA4B,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,EAAE,CAAC,oBAAoB;QAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,IAAI,EAAE,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,8GAA8G,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAClK,CAAC;SAAM,IAAI,EAAE,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,8DAA8D,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5G,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,IAAc;IAC3C,MAAM,GAAG,GAAG,IAAA,kBAAS,GAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,IAAA,2BAAkB,GAAE,CAAC;IAEtC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,kHAAkH,CAAC,CAAC;QAClI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,IAAA,qBAAY,EAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,IAAA,eAAM,EACtB,GAAG,GAAG,CAAC,MAAM,cAAc,KAAK,CAAC,EAAE,yBAAyB,KAAK,EAAE,EAAE,GAAG,CAAC,MAAM,CAChF,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,cAAc,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,mBAAmB,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC;IAChC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,oHAAoH,CAAC,CAAC;QAClI,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC,YAAY;YAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,YAAY,MAAM,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,cAAc,eAAe,CAAC,CAAC,UAAU,WAAW,CAAC,CAAC,YAAY,WAAW,CAAC,CAAC;QACtJ,OAAO,CAAC,GAAG,CAAC,sBAAsB,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACtG,IAAI,CAAC,CAAC,iBAAiB;YAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACzF,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,gBAAgB,SAAS,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAC;QACrG,IAAI,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC5B,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY,EAAE,QAAgB;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACvD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC;AAED,SAAS,SAAS,CAAC,CAAiB;IAClC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,KAAa,EAAE,KAAkB;IACpD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7H,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC;AAC9F,CAAC;AAED;8DAC8D;AAC9D,SAAS,OAAO,CAAC,GAAY;IAC3B,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,GAAG,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC;IACjD,IAAI,GAAW,CAAC;IAChB,IAAI,GAAG,GAAG,MAAM;QAAE,GAAG,GAAG,UAAU,CAAC;SAC9B,IAAI,CAAC,GAAG,CAAC;QAAE,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;SACzB,IAAI,CAAC,GAAG,EAAE;QAAE,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;;QAC1B,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;IACpC,MAAM,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;IACzE,OAAO,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;AAC3B,CAAC"}
|