@mandible-ai/mandible 0.2.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/LICENSE +21 -0
- package/README.md +391 -0
- package/dist/examples/code-pipeline/index.d.ts +3 -0
- package/dist/examples/code-pipeline/index.d.ts.map +1 -0
- package/dist/examples/code-pipeline/index.js +239 -0
- package/dist/examples/code-pipeline/index.js.map +1 -0
- package/dist/examples/code-pipeline/with-providers.d.ts +3 -0
- package/dist/examples/code-pipeline/with-providers.d.ts.map +1 -0
- package/dist/examples/code-pipeline/with-providers.js +246 -0
- package/dist/examples/code-pipeline/with-providers.js.map +1 -0
- package/dist/examples/docker-pipeline/index.d.ts +3 -0
- package/dist/examples/docker-pipeline/index.d.ts.map +1 -0
- package/dist/examples/docker-pipeline/index.js +235 -0
- package/dist/examples/docker-pipeline/index.js.map +1 -0
- package/dist/examples/github-colony/mandible.config.d.ts +11 -0
- package/dist/examples/github-colony/mandible.config.d.ts.map +1 -0
- package/dist/examples/github-colony/mandible.config.js +63 -0
- package/dist/examples/github-colony/mandible.config.js.map +1 -0
- package/dist/examples/remote-pipeline/index.d.ts +3 -0
- package/dist/examples/remote-pipeline/index.d.ts.map +1 -0
- package/dist/examples/remote-pipeline/index.js +154 -0
- package/dist/examples/remote-pipeline/index.js.map +1 -0
- package/dist/examples/repo-maintenance/fixer.d.ts +80 -0
- package/dist/examples/repo-maintenance/fixer.d.ts.map +1 -0
- package/dist/examples/repo-maintenance/fixer.js +217 -0
- package/dist/examples/repo-maintenance/fixer.js.map +1 -0
- package/dist/examples/repo-maintenance/mandible.config.d.ts +11 -0
- package/dist/examples/repo-maintenance/mandible.config.d.ts.map +1 -0
- package/dist/examples/repo-maintenance/mandible.config.js +34 -0
- package/dist/examples/repo-maintenance/mandible.config.js.map +1 -0
- package/dist/examples/repo-maintenance/scout.d.ts +39 -0
- package/dist/examples/repo-maintenance/scout.d.ts.map +1 -0
- package/dist/examples/repo-maintenance/scout.js +163 -0
- package/dist/examples/repo-maintenance/scout.js.map +1 -0
- package/dist/examples/repo-maintenance/seed.d.ts +3 -0
- package/dist/examples/repo-maintenance/seed.d.ts.map +1 -0
- package/dist/examples/repo-maintenance/seed.js +169 -0
- package/dist/examples/repo-maintenance/seed.js.map +1 -0
- package/dist/src/cli/index.d.ts +3 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +116 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/server.d.ts +15 -0
- package/dist/src/cli/server.d.ts.map +1 -0
- package/dist/src/cli/server.js +204 -0
- package/dist/src/cli/server.js.map +1 -0
- package/dist/src/cloud/client.d.ts +30 -0
- package/dist/src/cloud/client.d.ts.map +1 -0
- package/dist/src/cloud/client.js +124 -0
- package/dist/src/cloud/client.js.map +1 -0
- package/dist/src/cloud/index.d.ts +5 -0
- package/dist/src/cloud/index.d.ts.map +1 -0
- package/dist/src/cloud/index.js +3 -0
- package/dist/src/cloud/index.js.map +1 -0
- package/dist/src/cloud/types.d.ts +104 -0
- package/dist/src/cloud/types.d.ts.map +1 -0
- package/dist/src/cloud/types.js +9 -0
- package/dist/src/cloud/types.js.map +1 -0
- package/dist/src/core/attestation.d.ts +63 -0
- package/dist/src/core/attestation.d.ts.map +1 -0
- package/dist/src/core/attestation.js +331 -0
- package/dist/src/core/attestation.js.map +1 -0
- package/dist/src/core/events.d.ts +22 -0
- package/dist/src/core/events.d.ts.map +1 -0
- package/dist/src/core/events.js +45 -0
- package/dist/src/core/events.js.map +1 -0
- package/dist/src/core/index.d.ts +8 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +7 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/core/runtime.d.ts +57 -0
- package/dist/src/core/runtime.d.ts.map +1 -0
- package/dist/src/core/runtime.js +564 -0
- package/dist/src/core/runtime.js.map +1 -0
- package/dist/src/core/signal.d.ts +33 -0
- package/dist/src/core/signal.d.ts.map +1 -0
- package/dist/src/core/signal.js +127 -0
- package/dist/src/core/signal.js.map +1 -0
- package/dist/src/core/types.d.ts +395 -0
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/types.js +19 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/core/validation.d.ts +10 -0
- package/dist/src/core/validation.d.ts.map +1 -0
- package/dist/src/core/validation.js +40 -0
- package/dist/src/core/validation.js.map +1 -0
- package/dist/src/dsl/builder.d.ts +63 -0
- package/dist/src/dsl/builder.d.ts.map +1 -0
- package/dist/src/dsl/builder.js +159 -0
- package/dist/src/dsl/builder.js.map +1 -0
- package/dist/src/dsl/index.d.ts +2 -0
- package/dist/src/dsl/index.d.ts.map +1 -0
- package/dist/src/dsl/index.js +2 -0
- package/dist/src/dsl/index.js.map +1 -0
- package/dist/src/environments/dolt/adapter.d.ts +45 -0
- package/dist/src/environments/dolt/adapter.d.ts.map +1 -0
- package/dist/src/environments/dolt/adapter.js +128 -0
- package/dist/src/environments/dolt/adapter.js.map +1 -0
- package/dist/src/environments/dolt/index.d.ts +2 -0
- package/dist/src/environments/dolt/index.d.ts.map +1 -0
- package/dist/src/environments/dolt/index.js +2 -0
- package/dist/src/environments/dolt/index.js.map +1 -0
- package/dist/src/environments/filesystem/adapter.d.ts +33 -0
- package/dist/src/environments/filesystem/adapter.d.ts.map +1 -0
- package/dist/src/environments/filesystem/adapter.js +296 -0
- package/dist/src/environments/filesystem/adapter.js.map +1 -0
- package/dist/src/environments/filesystem/index.d.ts +2 -0
- package/dist/src/environments/filesystem/index.d.ts.map +1 -0
- package/dist/src/environments/filesystem/index.js +2 -0
- package/dist/src/environments/filesystem/index.js.map +1 -0
- package/dist/src/environments/github/adapter.d.ts +47 -0
- package/dist/src/environments/github/adapter.d.ts.map +1 -0
- package/dist/src/environments/github/adapter.js +324 -0
- package/dist/src/environments/github/adapter.js.map +1 -0
- package/dist/src/environments/github/client.d.ts +48 -0
- package/dist/src/environments/github/client.d.ts.map +1 -0
- package/dist/src/environments/github/client.js +151 -0
- package/dist/src/environments/github/client.js.map +1 -0
- package/dist/src/environments/github/index.d.ts +5 -0
- package/dist/src/environments/github/index.d.ts.map +1 -0
- package/dist/src/environments/github/index.js +5 -0
- package/dist/src/environments/github/index.js.map +1 -0
- package/dist/src/environments/github/mapper.d.ts +66 -0
- package/dist/src/environments/github/mapper.d.ts.map +1 -0
- package/dist/src/environments/github/mapper.js +240 -0
- package/dist/src/environments/github/mapper.js.map +1 -0
- package/dist/src/environments/github/types.d.ts +71 -0
- package/dist/src/environments/github/types.d.ts.map +1 -0
- package/dist/src/environments/github/types.js +4 -0
- package/dist/src/environments/github/types.js.map +1 -0
- package/dist/src/environments/remote/adapter.d.ts +61 -0
- package/dist/src/environments/remote/adapter.d.ts.map +1 -0
- package/dist/src/environments/remote/adapter.js +392 -0
- package/dist/src/environments/remote/adapter.js.map +1 -0
- package/dist/src/environments/remote/index.d.ts +5 -0
- package/dist/src/environments/remote/index.d.ts.map +1 -0
- package/dist/src/environments/remote/index.js +3 -0
- package/dist/src/environments/remote/index.js.map +1 -0
- package/dist/src/environments/remote/protocol.d.ts +124 -0
- package/dist/src/environments/remote/protocol.d.ts.map +1 -0
- package/dist/src/environments/remote/protocol.js +24 -0
- package/dist/src/environments/remote/protocol.js.map +1 -0
- package/dist/src/index.d.ts +25 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +31 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/patterns/bridge.d.ts +32 -0
- package/dist/src/patterns/bridge.d.ts.map +1 -0
- package/dist/src/patterns/bridge.js +163 -0
- package/dist/src/patterns/bridge.js.map +1 -0
- package/dist/src/patterns/index.d.ts +5 -0
- package/dist/src/patterns/index.d.ts.map +1 -0
- package/dist/src/patterns/index.js +3 -0
- package/dist/src/patterns/index.js.map +1 -0
- package/dist/src/patterns/sentinel.d.ts +69 -0
- package/dist/src/patterns/sentinel.d.ts.map +1 -0
- package/dist/src/patterns/sentinel.js +184 -0
- package/dist/src/patterns/sentinel.js.map +1 -0
- package/dist/src/providers/agent.d.ts +23 -0
- package/dist/src/providers/agent.d.ts.map +1 -0
- package/dist/src/providers/agent.js +184 -0
- package/dist/src/providers/agent.js.map +1 -0
- package/dist/src/providers/bash.d.ts +13 -0
- package/dist/src/providers/bash.d.ts.map +1 -0
- package/dist/src/providers/bash.js +91 -0
- package/dist/src/providers/bash.js.map +1 -0
- package/dist/src/providers/claude-code.d.ts +23 -0
- package/dist/src/providers/claude-code.d.ts.map +1 -0
- package/dist/src/providers/claude-code.js +184 -0
- package/dist/src/providers/claude-code.js.map +1 -0
- package/dist/src/providers/context.d.ts +12 -0
- package/dist/src/providers/context.d.ts.map +1 -0
- package/dist/src/providers/context.js +160 -0
- package/dist/src/providers/context.js.map +1 -0
- package/dist/src/providers/index.d.ts +6 -0
- package/dist/src/providers/index.d.ts.map +1 -0
- package/dist/src/providers/index.js +7 -0
- package/dist/src/providers/index.js.map +1 -0
- package/dist/src/providers/structured-output.d.ts +7 -0
- package/dist/src/providers/structured-output.d.ts.map +1 -0
- package/dist/src/providers/structured-output.js +316 -0
- package/dist/src/providers/structured-output.js.map +1 -0
- package/dist/src/providers/types.d.ts +239 -0
- package/dist/src/providers/types.d.ts.map +1 -0
- package/dist/src/providers/types.js +19 -0
- package/dist/src/providers/types.js.map +1 -0
- package/package.json +129 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
// PURPOSE: GitHub environment adapter — GitHub Issues as a stigmergy substrate
|
|
2
|
+
// PURPOSE: Polling with ETag caching, concentration reinforcement, advisory claims
|
|
3
|
+
import { matchesQuery, isClaimExpired } from '../../core/signal.js';
|
|
4
|
+
import { validateSignalInput } from '../../core/validation.js';
|
|
5
|
+
import { GitHubClient } from './client.js';
|
|
6
|
+
import { defaultTypeMapper, defaultPayloadMapper, defaultConcentrationMapper, defaultDependencyMapper, computeDependencyBoosts, } from './mapper.js';
|
|
7
|
+
export class GitHubEnvironment {
|
|
8
|
+
name;
|
|
9
|
+
config;
|
|
10
|
+
client;
|
|
11
|
+
typeMapper;
|
|
12
|
+
payloadMapper;
|
|
13
|
+
concentrationMapper;
|
|
14
|
+
dependencyMapper;
|
|
15
|
+
issueFilter;
|
|
16
|
+
decayRate;
|
|
17
|
+
concentrationFloor;
|
|
18
|
+
// In-memory signal cache — GitHub API is source of truth
|
|
19
|
+
signals = new Map();
|
|
20
|
+
withdrawn = new Map();
|
|
21
|
+
// Tracking for decay
|
|
22
|
+
lastSyncAt = Date.now();
|
|
23
|
+
lastDecayAt = Date.now();
|
|
24
|
+
initialized = false;
|
|
25
|
+
constructor(config) {
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.name = config.name ?? `gh:${config.owner}/${config.repo}`;
|
|
28
|
+
this.client = new GitHubClient(config);
|
|
29
|
+
this.typeMapper = config.typeMapper ?? defaultTypeMapper;
|
|
30
|
+
this.payloadMapper = config.payloadMapper ?? defaultPayloadMapper;
|
|
31
|
+
this.concentrationMapper = config.concentrationMapper ?? defaultConcentrationMapper;
|
|
32
|
+
this.dependencyMapper = config.dependencyMapper ?? defaultDependencyMapper;
|
|
33
|
+
this.issueFilter = config.issueFilter;
|
|
34
|
+
this.decayRate = config.decayRate ?? 0.001;
|
|
35
|
+
this.concentrationFloor = config.concentrationFloor ?? 0.05;
|
|
36
|
+
}
|
|
37
|
+
// ----------------------------------------------------------
|
|
38
|
+
// Signal ID — deterministic mapping from issue number
|
|
39
|
+
// ----------------------------------------------------------
|
|
40
|
+
signalId(issueNumber) {
|
|
41
|
+
return `gh:${this.config.owner}/${this.config.repo}#${issueNumber}`;
|
|
42
|
+
}
|
|
43
|
+
issueNumberFromSignalId(signalId) {
|
|
44
|
+
const match = signalId.match(/#(\d+)$/);
|
|
45
|
+
return match ? parseInt(match[1], 10) : null;
|
|
46
|
+
}
|
|
47
|
+
// ----------------------------------------------------------
|
|
48
|
+
// Issue → Signal conversion
|
|
49
|
+
// ----------------------------------------------------------
|
|
50
|
+
issueToSignal(issue) {
|
|
51
|
+
const id = this.signalId(issue.number);
|
|
52
|
+
const type = this.typeMapper(issue);
|
|
53
|
+
const payload = this.payloadMapper(issue);
|
|
54
|
+
const concentration = this.concentrationMapper(issue, this.config);
|
|
55
|
+
const tags = issue.labels.map(l => l.name);
|
|
56
|
+
const signal = {
|
|
57
|
+
id,
|
|
58
|
+
type,
|
|
59
|
+
payload,
|
|
60
|
+
meta: {
|
|
61
|
+
deposited_at: new Date(issue.created_at).getTime(),
|
|
62
|
+
deposited_by: 'github',
|
|
63
|
+
concentration,
|
|
64
|
+
tags,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
// Wire dependency edges via pluggable mapper
|
|
68
|
+
const depIds = this.dependencyMapper(issue, this.config);
|
|
69
|
+
if (depIds.length > 0) {
|
|
70
|
+
signal.meta.caused_by = depIds;
|
|
71
|
+
}
|
|
72
|
+
return signal;
|
|
73
|
+
}
|
|
74
|
+
// ----------------------------------------------------------
|
|
75
|
+
// Sync from GitHub API
|
|
76
|
+
// ----------------------------------------------------------
|
|
77
|
+
async ensureInit() {
|
|
78
|
+
if (this.initialized)
|
|
79
|
+
return;
|
|
80
|
+
await this.syncFromGitHub();
|
|
81
|
+
this.initialized = true;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Core sync method. Fetches issues from GitHub and updates local cache.
|
|
85
|
+
* Returns the list of new signal IDs that appeared since last sync.
|
|
86
|
+
*/
|
|
87
|
+
async syncFromGitHub() {
|
|
88
|
+
const result = await this.client.fetchIssues();
|
|
89
|
+
// 304 Not Modified — no changes since last poll
|
|
90
|
+
if (result.issues === null) {
|
|
91
|
+
this.lastSyncAt = Date.now();
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
const newSignalIds = [];
|
|
95
|
+
const seenIds = new Set();
|
|
96
|
+
for (const issue of result.issues) {
|
|
97
|
+
// Skip pull requests (GitHub returns PRs in the issues endpoint)
|
|
98
|
+
if (issue.pull_request)
|
|
99
|
+
continue;
|
|
100
|
+
// Apply custom filter
|
|
101
|
+
if (this.issueFilter && !this.issueFilter(issue))
|
|
102
|
+
continue;
|
|
103
|
+
const freshSignal = this.issueToSignal(issue);
|
|
104
|
+
seenIds.add(freshSignal.id);
|
|
105
|
+
const existing = this.signals.get(freshSignal.id);
|
|
106
|
+
if (existing) {
|
|
107
|
+
// Reinforcement: take the max of current and fresh concentration
|
|
108
|
+
// Preserve claim state from local cache
|
|
109
|
+
freshSignal.meta.concentration = Math.max(existing.meta.concentration, freshSignal.meta.concentration);
|
|
110
|
+
freshSignal.meta.claimed_by = existing.meta.claimed_by;
|
|
111
|
+
freshSignal.meta.claimed_at = existing.meta.claimed_at;
|
|
112
|
+
freshSignal.meta.claim_lease = existing.meta.claim_lease;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
newSignalIds.push(freshSignal.id);
|
|
116
|
+
}
|
|
117
|
+
this.signals.set(freshSignal.id, freshSignal);
|
|
118
|
+
}
|
|
119
|
+
// Issues that disappeared from the API (closed externally) are NOT removed.
|
|
120
|
+
// They stop being reinforced and natural decay handles evaporation.
|
|
121
|
+
// This is the stigmergy way: absence of reinforcement = signal fades.
|
|
122
|
+
// Apply dependency-aware concentration adjustments (boosts and penalties)
|
|
123
|
+
const boosts = computeDependencyBoosts(this.signals, {
|
|
124
|
+
rootBoost: this.config.dependencyBoost?.rootBoost,
|
|
125
|
+
dependentBoost: this.config.dependencyBoost?.dependentBoost,
|
|
126
|
+
maxBoost: this.config.dependencyBoost?.maxBoost,
|
|
127
|
+
leafPenalty: this.config.dependencyBoost?.leafPenalty,
|
|
128
|
+
});
|
|
129
|
+
for (const [id, adjustment] of boosts) {
|
|
130
|
+
const signal = this.signals.get(id);
|
|
131
|
+
if (signal) {
|
|
132
|
+
signal.meta.concentration = Math.max(this.concentrationFloor, Math.min(1.0, signal.meta.concentration + adjustment));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
this.lastSyncAt = Date.now();
|
|
136
|
+
return newSignalIds;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Public method to force a manual refresh. Useful for testing.
|
|
140
|
+
*/
|
|
141
|
+
async sync() {
|
|
142
|
+
await this.syncFromGitHub();
|
|
143
|
+
this.initialized = true;
|
|
144
|
+
}
|
|
145
|
+
// ----------------------------------------------------------
|
|
146
|
+
// Environment interface implementation
|
|
147
|
+
// ----------------------------------------------------------
|
|
148
|
+
async observe(query) {
|
|
149
|
+
await this.ensureInit();
|
|
150
|
+
let matched = Array.from(this.signals.values()).filter(s => matchesQuery(s, query));
|
|
151
|
+
if (query.limit) {
|
|
152
|
+
matched = matched.slice(0, query.limit);
|
|
153
|
+
}
|
|
154
|
+
return matched;
|
|
155
|
+
}
|
|
156
|
+
async deposit(input) {
|
|
157
|
+
await this.ensureInit();
|
|
158
|
+
validateSignalInput(input);
|
|
159
|
+
if (this.config.allowDeposit === false) {
|
|
160
|
+
throw new Error('GitHubEnvironment: deposit (issue creation) is disabled via config');
|
|
161
|
+
}
|
|
162
|
+
// Create a real GitHub issue
|
|
163
|
+
const labels = input.meta?.tags ?? [];
|
|
164
|
+
const issue = await this.client.createIssue(input.payload.title ?? input.type, input.payload.body, labels);
|
|
165
|
+
const signal = this.issueToSignal(issue);
|
|
166
|
+
// Override with caller's meta if provided
|
|
167
|
+
if (input.meta?.deposited_by)
|
|
168
|
+
signal.meta.deposited_by = input.meta.deposited_by;
|
|
169
|
+
if (input.meta?.ttl)
|
|
170
|
+
signal.meta.ttl = input.meta.ttl;
|
|
171
|
+
if (input.meta?.caused_by)
|
|
172
|
+
signal.meta.caused_by = input.meta.caused_by;
|
|
173
|
+
if (input.meta?.concentration !== undefined)
|
|
174
|
+
signal.meta.concentration = input.meta.concentration;
|
|
175
|
+
this.signals.set(signal.id, signal);
|
|
176
|
+
return signal;
|
|
177
|
+
}
|
|
178
|
+
async withdraw(signalId) {
|
|
179
|
+
await this.ensureInit();
|
|
180
|
+
if (this.config.allowWithdraw === false) {
|
|
181
|
+
throw new Error('GitHubEnvironment: withdraw (issue closing) is disabled via config');
|
|
182
|
+
}
|
|
183
|
+
const issueNumber = this.issueNumberFromSignalId(signalId);
|
|
184
|
+
if (issueNumber !== null) {
|
|
185
|
+
await this.client.closeIssue(issueNumber);
|
|
186
|
+
}
|
|
187
|
+
const signal = this.signals.get(signalId);
|
|
188
|
+
if (signal) {
|
|
189
|
+
this.withdrawn.set(signalId, signal);
|
|
190
|
+
this.signals.delete(signalId);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async claim(signalId, claimant, leaseDuration = 60_000) {
|
|
194
|
+
await this.ensureInit();
|
|
195
|
+
const signal = this.signals.get(signalId);
|
|
196
|
+
if (!signal)
|
|
197
|
+
return false;
|
|
198
|
+
// Check existing claim
|
|
199
|
+
if (signal.meta.claimed_by) {
|
|
200
|
+
if (!isClaimExpired(signal)) {
|
|
201
|
+
return false; // Already claimed and not expired
|
|
202
|
+
}
|
|
203
|
+
// Expired claim — allow takeover
|
|
204
|
+
}
|
|
205
|
+
signal.meta.claimed_by = claimant;
|
|
206
|
+
signal.meta.claimed_at = Date.now();
|
|
207
|
+
signal.meta.claim_lease = leaseDuration;
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
async release(signalId) {
|
|
211
|
+
await this.ensureInit();
|
|
212
|
+
const signal = this.signals.get(signalId);
|
|
213
|
+
if (!signal)
|
|
214
|
+
return;
|
|
215
|
+
signal.meta.claimed_by = undefined;
|
|
216
|
+
signal.meta.claimed_at = undefined;
|
|
217
|
+
signal.meta.claim_lease = undefined;
|
|
218
|
+
}
|
|
219
|
+
watch(query, callback) {
|
|
220
|
+
const seen = new Set();
|
|
221
|
+
let active = true;
|
|
222
|
+
let pollTimer;
|
|
223
|
+
const pollInterval = this.config.pollInterval ?? 30_000;
|
|
224
|
+
const emitMatches = async () => {
|
|
225
|
+
if (!active)
|
|
226
|
+
return;
|
|
227
|
+
try {
|
|
228
|
+
const newIds = await this.syncFromGitHub();
|
|
229
|
+
if (!this.initialized)
|
|
230
|
+
this.initialized = true;
|
|
231
|
+
for (const [id, signal] of this.signals) {
|
|
232
|
+
if (!active)
|
|
233
|
+
return;
|
|
234
|
+
if (seen.has(id))
|
|
235
|
+
continue;
|
|
236
|
+
if (matchesQuery(signal, query)) {
|
|
237
|
+
seen.add(id);
|
|
238
|
+
callback(signal);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
// Swallow errors during poll — will retry next cycle
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
// Initial sync + emit
|
|
247
|
+
const setup = async () => {
|
|
248
|
+
await emitMatches();
|
|
249
|
+
if (!active)
|
|
250
|
+
return;
|
|
251
|
+
pollTimer = setInterval(emitMatches, pollInterval);
|
|
252
|
+
};
|
|
253
|
+
setup();
|
|
254
|
+
return {
|
|
255
|
+
unsubscribe() {
|
|
256
|
+
active = false;
|
|
257
|
+
if (pollTimer)
|
|
258
|
+
clearInterval(pollTimer);
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
async history(query) {
|
|
263
|
+
await this.ensureInit();
|
|
264
|
+
const active = Array.from(this.signals.values());
|
|
265
|
+
let all = active;
|
|
266
|
+
if (query.includeWithdrawn) {
|
|
267
|
+
const withdrawnSignals = Array.from(this.withdrawn.values());
|
|
268
|
+
all = [...active, ...withdrawnSignals];
|
|
269
|
+
}
|
|
270
|
+
let matched = all.filter(s => matchesQuery(s, query));
|
|
271
|
+
if (query.limit)
|
|
272
|
+
matched = matched.slice(0, query.limit);
|
|
273
|
+
return matched;
|
|
274
|
+
}
|
|
275
|
+
async decay() {
|
|
276
|
+
await this.ensureInit();
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
const result = { decayed: 0, evaporated: 0, claimsReleased: 0 };
|
|
279
|
+
// Elapsed since LAST DECAY (not last sync) — prevents quadratic compounding
|
|
280
|
+
const elapsedSeconds = (now - this.lastDecayAt) / 1000;
|
|
281
|
+
// Only apply concentration decay if meaningful time has passed
|
|
282
|
+
// (guards against multiple runtimes sharing this environment)
|
|
283
|
+
const shouldDecayConcentration = elapsedSeconds >= 0.1;
|
|
284
|
+
if (shouldDecayConcentration) {
|
|
285
|
+
this.lastDecayAt = now;
|
|
286
|
+
}
|
|
287
|
+
const decayAmount = shouldDecayConcentration ? this.decayRate * elapsedSeconds : 0;
|
|
288
|
+
for (const [id, signal] of this.signals) {
|
|
289
|
+
let changed = false;
|
|
290
|
+
// Always check claim lease expiration regardless of elapsed time
|
|
291
|
+
if (isClaimExpired(signal, now)) {
|
|
292
|
+
signal.meta.claimed_by = undefined;
|
|
293
|
+
signal.meta.claimed_at = undefined;
|
|
294
|
+
signal.meta.claim_lease = undefined;
|
|
295
|
+
result.claimsReleased++;
|
|
296
|
+
changed = true;
|
|
297
|
+
}
|
|
298
|
+
// Linear decay — same amount for all signals this sweep
|
|
299
|
+
const newConcentration = signal.meta.concentration - decayAmount;
|
|
300
|
+
if (newConcentration < this.concentrationFloor) {
|
|
301
|
+
// Below floor — evaporate
|
|
302
|
+
this.withdrawn.set(id, signal);
|
|
303
|
+
this.signals.delete(id);
|
|
304
|
+
result.evaporated++;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
if (Math.abs(newConcentration - signal.meta.concentration) > 0.0001) {
|
|
308
|
+
signal.meta.concentration = newConcentration;
|
|
309
|
+
changed = true;
|
|
310
|
+
result.decayed++;
|
|
311
|
+
}
|
|
312
|
+
// We don't write to disk — in-memory cache only
|
|
313
|
+
if (changed) {
|
|
314
|
+
this.signals.set(id, signal);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
async snapshot() {
|
|
320
|
+
await this.ensureInit();
|
|
321
|
+
return Array.from(this.signals.values());
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../src/environments/github/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { GitHubIssue, GitHubEnvConfig } from './types.js';
|
|
2
|
+
export interface RateLimitInfo {
|
|
3
|
+
remaining: number;
|
|
4
|
+
limit: number;
|
|
5
|
+
reset: number;
|
|
6
|
+
}
|
|
7
|
+
export interface FetchResult {
|
|
8
|
+
issues: GitHubIssue[] | null;
|
|
9
|
+
etag: string | null;
|
|
10
|
+
rateLimit: RateLimitInfo;
|
|
11
|
+
}
|
|
12
|
+
export declare class GitHubClient {
|
|
13
|
+
private readonly baseUrl;
|
|
14
|
+
private readonly owner;
|
|
15
|
+
private readonly repo;
|
|
16
|
+
private readonly token;
|
|
17
|
+
private readonly labels;
|
|
18
|
+
private _etag;
|
|
19
|
+
private _rateLimit;
|
|
20
|
+
constructor(config: GitHubEnvConfig);
|
|
21
|
+
get rateLimitInfo(): RateLimitInfo;
|
|
22
|
+
private headers;
|
|
23
|
+
private updateRateLimit;
|
|
24
|
+
/**
|
|
25
|
+
* Parse the Link header to get the next page URL.
|
|
26
|
+
* Format: <url>; rel="next", <url>; rel="last"
|
|
27
|
+
*/
|
|
28
|
+
private parseNextLink;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch open issues from the repository.
|
|
31
|
+
* Returns null if the server responds with 304 (no changes since last ETag).
|
|
32
|
+
* Handles pagination automatically for repos with >100 issues.
|
|
33
|
+
*/
|
|
34
|
+
fetchIssues(): Promise<FetchResult>;
|
|
35
|
+
/**
|
|
36
|
+
* Create a new issue in the repository.
|
|
37
|
+
*/
|
|
38
|
+
createIssue(title: string, body?: string, labels?: string[]): Promise<GitHubIssue>;
|
|
39
|
+
/**
|
|
40
|
+
* Close an issue by number.
|
|
41
|
+
*/
|
|
42
|
+
closeIssue(issueNumber: number): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Reset the stored ETag (forces a fresh fetch on next call).
|
|
45
|
+
*/
|
|
46
|
+
resetETag(): void;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/environments/github/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,UAAU,CAA6D;gBAEnE,MAAM,EAAE,eAAe;IAQnC,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,eAAe;IAUvB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAMrB;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC;IA+DzC;;OAEG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,WAAW,CAAC;IAuBvB;;OAEG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpD;;OAEG;IACH,SAAS,IAAI,IAAI;CAGlB"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// PURPOSE: Thin HTTP client for the GitHub Issues API
|
|
2
|
+
// PURPOSE: ETag caching, pagination via Link header, rate limit tracking
|
|
3
|
+
export class GitHubClient {
|
|
4
|
+
baseUrl;
|
|
5
|
+
owner;
|
|
6
|
+
repo;
|
|
7
|
+
token;
|
|
8
|
+
labels;
|
|
9
|
+
_etag = null;
|
|
10
|
+
_rateLimit = { remaining: 5000, limit: 5000, reset: 0 };
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.baseUrl = (config.apiBase ?? 'https://api.github.com').replace(/\/$/, '');
|
|
13
|
+
this.owner = config.owner;
|
|
14
|
+
this.repo = config.repo;
|
|
15
|
+
this.token = config.token ?? process.env.GITHUB_TOKEN;
|
|
16
|
+
this.labels = config.labels ?? [];
|
|
17
|
+
}
|
|
18
|
+
get rateLimitInfo() {
|
|
19
|
+
return { ...this._rateLimit };
|
|
20
|
+
}
|
|
21
|
+
headers(extraHeaders) {
|
|
22
|
+
const h = {
|
|
23
|
+
'Accept': 'application/vnd.github+json',
|
|
24
|
+
'User-Agent': 'mandible-stigmergy',
|
|
25
|
+
...extraHeaders,
|
|
26
|
+
};
|
|
27
|
+
if (this.token) {
|
|
28
|
+
h['Authorization'] = `Bearer ${this.token}`;
|
|
29
|
+
}
|
|
30
|
+
return h;
|
|
31
|
+
}
|
|
32
|
+
updateRateLimit(headers) {
|
|
33
|
+
const remaining = headers.get('x-ratelimit-remaining');
|
|
34
|
+
const limit = headers.get('x-ratelimit-limit');
|
|
35
|
+
const reset = headers.get('x-ratelimit-reset');
|
|
36
|
+
if (remaining !== null)
|
|
37
|
+
this._rateLimit.remaining = parseInt(remaining, 10);
|
|
38
|
+
if (limit !== null)
|
|
39
|
+
this._rateLimit.limit = parseInt(limit, 10);
|
|
40
|
+
if (reset !== null)
|
|
41
|
+
this._rateLimit.reset = parseInt(reset, 10);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse the Link header to get the next page URL.
|
|
45
|
+
* Format: <url>; rel="next", <url>; rel="last"
|
|
46
|
+
*/
|
|
47
|
+
parseNextLink(linkHeader) {
|
|
48
|
+
if (!linkHeader)
|
|
49
|
+
return null;
|
|
50
|
+
const match = linkHeader.match(/<([^>]+)>;\s*rel="next"/);
|
|
51
|
+
return match ? match[1] : null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Fetch open issues from the repository.
|
|
55
|
+
* Returns null if the server responds with 304 (no changes since last ETag).
|
|
56
|
+
* Handles pagination automatically for repos with >100 issues.
|
|
57
|
+
*/
|
|
58
|
+
async fetchIssues() {
|
|
59
|
+
const params = new URLSearchParams({
|
|
60
|
+
state: 'open',
|
|
61
|
+
per_page: '100',
|
|
62
|
+
sort: 'updated',
|
|
63
|
+
direction: 'desc',
|
|
64
|
+
});
|
|
65
|
+
if (this.labels.length > 0) {
|
|
66
|
+
params.set('labels', this.labels.join(','));
|
|
67
|
+
}
|
|
68
|
+
const url = `${this.baseUrl}/repos/${this.owner}/${this.repo}/issues?${params}`;
|
|
69
|
+
const extraHeaders = {};
|
|
70
|
+
if (this._etag) {
|
|
71
|
+
extraHeaders['If-None-Match'] = this._etag;
|
|
72
|
+
}
|
|
73
|
+
const response = await fetch(url, { headers: this.headers(extraHeaders) });
|
|
74
|
+
this.updateRateLimit(response.headers);
|
|
75
|
+
// 304 Not Modified — no changes
|
|
76
|
+
if (response.status === 304) {
|
|
77
|
+
return {
|
|
78
|
+
issues: null,
|
|
79
|
+
etag: this._etag,
|
|
80
|
+
rateLimit: this.rateLimitInfo,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw new Error(`GitHub API error: ${response.status} ${response.statusText} for ${url}`);
|
|
85
|
+
}
|
|
86
|
+
// Store ETag for next request
|
|
87
|
+
const etag = response.headers.get('etag');
|
|
88
|
+
if (etag)
|
|
89
|
+
this._etag = etag;
|
|
90
|
+
let issues = await response.json();
|
|
91
|
+
// Handle pagination
|
|
92
|
+
let nextUrl = this.parseNextLink(response.headers.get('link'));
|
|
93
|
+
while (nextUrl) {
|
|
94
|
+
const pageResponse = await fetch(nextUrl, { headers: this.headers() });
|
|
95
|
+
this.updateRateLimit(pageResponse.headers);
|
|
96
|
+
if (!pageResponse.ok)
|
|
97
|
+
break;
|
|
98
|
+
const pageIssues = await pageResponse.json();
|
|
99
|
+
issues = issues.concat(pageIssues);
|
|
100
|
+
nextUrl = this.parseNextLink(pageResponse.headers.get('link'));
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
issues,
|
|
104
|
+
etag: this._etag,
|
|
105
|
+
rateLimit: this.rateLimitInfo,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a new issue in the repository.
|
|
110
|
+
*/
|
|
111
|
+
async createIssue(title, body, labels) {
|
|
112
|
+
const url = `${this.baseUrl}/repos/${this.owner}/${this.repo}/issues`;
|
|
113
|
+
const payload = { title };
|
|
114
|
+
if (body)
|
|
115
|
+
payload.body = body;
|
|
116
|
+
if (labels && labels.length > 0)
|
|
117
|
+
payload.labels = labels;
|
|
118
|
+
const response = await fetch(url, {
|
|
119
|
+
method: 'POST',
|
|
120
|
+
headers: this.headers({ 'Content-Type': 'application/json' }),
|
|
121
|
+
body: JSON.stringify(payload),
|
|
122
|
+
});
|
|
123
|
+
this.updateRateLimit(response.headers);
|
|
124
|
+
if (!response.ok) {
|
|
125
|
+
throw new Error(`GitHub API error creating issue: ${response.status} ${response.statusText}`);
|
|
126
|
+
}
|
|
127
|
+
return await response.json();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Close an issue by number.
|
|
131
|
+
*/
|
|
132
|
+
async closeIssue(issueNumber) {
|
|
133
|
+
const url = `${this.baseUrl}/repos/${this.owner}/${this.repo}/issues/${issueNumber}`;
|
|
134
|
+
const response = await fetch(url, {
|
|
135
|
+
method: 'PATCH',
|
|
136
|
+
headers: this.headers({ 'Content-Type': 'application/json' }),
|
|
137
|
+
body: JSON.stringify({ state: 'closed' }),
|
|
138
|
+
});
|
|
139
|
+
this.updateRateLimit(response.headers);
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
throw new Error(`GitHub API error closing issue #${issueNumber}: ${response.status} ${response.statusText}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Reset the stored ETag (forces a fresh fetch on next call).
|
|
146
|
+
*/
|
|
147
|
+
resetETag() {
|
|
148
|
+
this._etag = null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/environments/github/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { GitHubEnvironment } from './adapter.js';
|
|
2
|
+
export type { GitHubEnvConfig, GitHubIssue, ConcentrationMapper } from './types.js';
|
|
3
|
+
export { defaultTypeMapper, defaultPayloadMapper, defaultConcentrationMapper, defaultDependencyMapper, parseDependencyIds, computeFreshness, parseGolemBody, } from './mapper.js';
|
|
4
|
+
export type { GolemBodySections } from './mapper.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/environments/github/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// PURPOSE: Barrel export for the GitHub environment adapter
|
|
2
|
+
// PURPOSE: Re-exports adapter, types, and mapper utilities
|
|
3
|
+
export { GitHubEnvironment } from './adapter.js';
|
|
4
|
+
export { defaultTypeMapper, defaultPayloadMapper, defaultConcentrationMapper, defaultDependencyMapper, parseDependencyIds, computeFreshness, parseGolemBody, } from './mapper.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/environments/github/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,2DAA2D;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { GitHubIssue, GitHubEnvConfig } from './types.js';
|
|
2
|
+
import type { Signal } from '../../core/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Derives a signal type from issue labels.
|
|
5
|
+
* Priority order:
|
|
6
|
+
* 1. golem + tablet labels → 'golem:tablet'
|
|
7
|
+
* 2. First recognized category label → 'issue:{category}'
|
|
8
|
+
* 3. Fallback → 'issue:open'
|
|
9
|
+
*/
|
|
10
|
+
export declare function defaultTypeMapper(issue: GitHubIssue): string;
|
|
11
|
+
export interface GolemBodySections {
|
|
12
|
+
acceptanceCriteria?: string[];
|
|
13
|
+
files?: string[];
|
|
14
|
+
dependencies?: string[];
|
|
15
|
+
risk?: string;
|
|
16
|
+
effort?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse structured Golem tablet body markdown.
|
|
21
|
+
* Extracts sections like acceptance criteria, files, dependencies, risk/effort.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseGolemBody(body: string | null): GolemBodySections;
|
|
24
|
+
/**
|
|
25
|
+
* Extract signal IDs from golem dependency strings.
|
|
26
|
+
* Recognizes beadId format: bd-{prefix}.{number} → gh:{owner}/{repo}#{number}
|
|
27
|
+
* Skips headers ("Blocked by:"), separators ("---"), and unrecognized text.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseDependencyIds(dependencies: string[], owner: string, repo: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Default dependency mapper — Golem-aware.
|
|
32
|
+
* Parses the Golem body's dependencies section for beadId references.
|
|
33
|
+
* Returns empty array for non-Golem issues or issues without dependencies.
|
|
34
|
+
*/
|
|
35
|
+
export declare function defaultDependencyMapper(issue: GitHubIssue, config: GitHubEnvConfig): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Extracts issue fields and parsed Golem body into a signal payload.
|
|
38
|
+
*/
|
|
39
|
+
export declare function defaultPayloadMapper(issue: GitHubIssue): Record<string, unknown>;
|
|
40
|
+
/**
|
|
41
|
+
* Compute base freshness from issue updated_at.
|
|
42
|
+
* Returns 1.0 for just-updated issues, decays linearly to 0 at maxStaleHours.
|
|
43
|
+
*/
|
|
44
|
+
export declare function computeFreshness(issue: GitHubIssue, maxStaleHours: number, floor: number): number;
|
|
45
|
+
/**
|
|
46
|
+
* Default concentration mapper using composite score:
|
|
47
|
+
* base_freshness + comment_boost + assigned_boost + milestone_boost
|
|
48
|
+
*
|
|
49
|
+
* All data comes from the issue object — zero extra API calls.
|
|
50
|
+
*/
|
|
51
|
+
export declare function defaultConcentrationMapper(issue: GitHubIssue, config: GitHubEnvConfig): number;
|
|
52
|
+
/**
|
|
53
|
+
* Compute concentration adjustments based on the dependency graph.
|
|
54
|
+
* Signals that unblock more downstream work get higher concentration.
|
|
55
|
+
* Leaf nodes (depend on others, nothing depends on them) get penalized.
|
|
56
|
+
*
|
|
57
|
+
* Returns positive values (boosts) and negative values (penalties).
|
|
58
|
+
* Does NOT mutate the input signals.
|
|
59
|
+
*/
|
|
60
|
+
export declare function computeDependencyBoosts(signals: Map<string, Signal>, options?: {
|
|
61
|
+
rootBoost?: number;
|
|
62
|
+
dependentBoost?: number;
|
|
63
|
+
maxBoost?: number;
|
|
64
|
+
leafPenalty?: number;
|
|
65
|
+
}): Map<string, number>;
|
|
66
|
+
//# sourceMappingURL=mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../../src/environments/github/mapper.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAMlD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAiB5D;AAMD,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,CAqErE;AAMD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,MAAM,EAAE,CASV;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,eAAe,GACtB,MAAM,EAAE,CAQV;AAMD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBhF;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,GACZ,MAAM,CAKR;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,eAAe,GACtB,MAAM,CAWR;AAMD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAyCrB"}
|