@bridge_gpt/mcp-server 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -15
- package/build/agent-config-credential-migration.js +272 -0
- package/build/agents.generated.js +1 -1
- package/build/chain-orchestrator.js +16 -1
- package/build/commands.generated.js +9 -7
- package/build/conductor/bridge-api-client.js +625 -0
- package/build/conductor/claude-hook.js +251 -0
- package/build/conductor/cli.js +1048 -0
- package/build/conductor/data-normalization.js +114 -0
- package/build/conductor/doctor.js +164 -0
- package/build/conductor/done-gate.js +325 -0
- package/build/conductor/epic-reconcile.js +139 -0
- package/build/conductor/epic-runtime.js +611 -0
- package/build/conductor/epic-state.js +125 -0
- package/build/conductor/errors.js +85 -0
- package/build/conductor/git-ci-types.js +129 -0
- package/build/conductor/git-hooks.js +218 -0
- package/build/conductor/git-inspection.js +185 -0
- package/build/conductor/git-producer.js +137 -0
- package/build/conductor/merge-ledger.js +198 -0
- package/build/conductor/paths.js +224 -0
- package/build/conductor/plan.js +77 -0
- package/build/conductor/pr-ci-producer.js +427 -0
- package/build/conductor/pr-discovery.js +135 -0
- package/build/conductor/producer-ledger.js +125 -0
- package/build/conductor/redaction.js +112 -0
- package/build/conductor/store.js +1156 -0
- package/build/conductor/supervisor-config.js +150 -0
- package/build/conductor/supervisor-escalation.js +244 -0
- package/build/conductor/supervisor-judgment-python.js +141 -0
- package/build/conductor/supervisor-judgment.js +215 -0
- package/build/conductor/supervisor-ledger.js +119 -0
- package/build/conductor/supervisor-merge.js +127 -0
- package/build/conductor/supervisor-message-relay.js +61 -0
- package/build/conductor/supervisor-notification.js +39 -0
- package/build/conductor/supervisor-runtime.js +351 -0
- package/build/conductor/supervisor-state.js +572 -0
- package/build/conductor/supervisor-types.js +16 -0
- package/build/conductor/taxonomy.js +58 -0
- package/build/conductor/tools.js +367 -0
- package/build/conductor/types.js +9 -0
- package/build/conductor-bin.js +21 -0
- package/build/conductor-claude-hook-bin.js +21 -0
- package/build/credential-store.js +175 -4
- package/build/credentials-cli.js +223 -0
- package/build/decision-page-schema.js +60 -0
- package/build/decision-page-template.js +262 -10
- package/build/doctor.js +5 -1
- package/build/index.js +558 -63
- package/build/pipeline-orchestrator.js +5 -1
- package/build/pipeline-utils.js +45 -5
- package/build/pipelines.generated.js +37 -9
- package/build/readme.generated.js +3 -0
- package/build/review-tickets.js +596 -0
- package/build/scheduled-prompt.js +16 -10
- package/build/start-tickets-conductor.js +496 -0
- package/build/start-tickets-prereqs.js +32 -23
- package/build/start-tickets-repo.js +49 -0
- package/build/start-tickets.js +683 -82
- package/build/version.generated.js +1 -1
- package/design-assets/favicon/android-chrome-192x192.png +0 -0
- package/design-assets/favicon/android-chrome-512x512.png +0 -0
- package/design-assets/favicon/apple-touch-icon.png +0 -0
- package/design-assets/favicon/favicon-16x16.png +0 -0
- package/design-assets/favicon/favicon-32x32.png +0 -0
- package/design-assets/favicon/favicon.ico +0 -0
- package/design-assets/favicon/site.webmanifest +1 -0
- package/design-assets/just-logo-rough-draft.png +0 -0
- package/package.json +18 -6
- package/pipelines/idea-to-ticket.json +5 -0
- package/pipelines/plan-epic.json +16 -1
- package/pipelines/review-ticket.json +2 -1
- package/public/css/main.min.css +2 -0
- package/public/css/main.min.css.map +1 -0
- package/public/fonts/OFL.txt +93 -0
- package/public/fonts/SourceSansPro-Black.ttf +0 -0
- package/public/fonts/SourceSansPro-BlackItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Bold.ttf +0 -0
- package/public/fonts/SourceSansPro-BoldItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-ExtraLight.ttf +0 -0
- package/public/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Italic.ttf +0 -0
- package/public/fonts/SourceSansPro-Light.ttf +0 -0
- package/public/fonts/SourceSansPro-LightItalic.ttf +0 -0
- package/public/fonts/SourceSansPro-Regular.ttf +0 -0
- package/public/fonts/SourceSansPro-SemiBold.ttf +0 -0
- package/public/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
- package/public/img/bridge-logo-160x51.webp +0 -0
- package/public/img/bridge-logo-300x92.webp +0 -0
- package/public/img/favicon/android-chrome-192x192.png +0 -0
- package/public/img/favicon/android-chrome-512x512.png +0 -0
- package/public/img/favicon/apple-touch-icon.png +0 -0
- package/public/img/favicon/favicon-16x16.png +0 -0
- package/public/img/favicon/favicon-32x32.png +0 -0
- package/public/img/favicon/favicon.ico +0 -0
- package/public/img/favicon/site.webmanifest +1 -0
- package/public/img/installation/bitbucket/app-password-1.png +0 -0
- package/public/img/installation/bitbucket/app-password-2.png +0 -0
- package/public/img/installation/bitbucket/create-token-1.png +0 -0
- package/public/img/installation/bitbucket/create-token-2.png +0 -0
- package/public/img/installation/bitbucket/webhook-1.png +0 -0
- package/public/img/installation/github/github-review-webhook.png +0 -0
- package/public/img/installation/jira/credentials/api-key.png +0 -0
- package/public/img/installation/jira/webhook/create-rule.png +0 -0
- package/public/img/installation/jira/webhook/project-settings.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-1.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-2.png +0 -0
- package/public/img/installation/jira/webhook/rule-create-3.png +0 -0
- package/public/img/installation/pinecone/pinecone-api-key.png +0 -0
- package/public/img/installation/pinecone/pinecone-index.png +0 -0
- package/public/js/main.min.js +2 -0
- package/public/js/main.min.js.map +1 -0
- package/smoke-test/SMOKE-TEST.md +16 -8
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic observed→desired reconciliation for the Epic Supervisor
|
|
3
|
+
* (BAPI-408).
|
|
4
|
+
*
|
|
5
|
+
* Executes five steps in order:
|
|
6
|
+
* 1. Fold terminal signals into Postgres via CAS
|
|
7
|
+
* 2. Compute the ready-set (pure, no LLM — Goal 8)
|
|
8
|
+
* 3. Dispatch ready tickets idempotently (key claim → spawn → correlate)
|
|
9
|
+
* 4. Action approved merges via C6 delegation
|
|
10
|
+
* 5. Schedule post-action wait hooks
|
|
11
|
+
*
|
|
12
|
+
* All durable mutations go through injected seams so the logic is testable
|
|
13
|
+
* without real network, ledger, or terminal access.
|
|
14
|
+
*/
|
|
15
|
+
import { computeReadySet } from "./epic-state.js";
|
|
16
|
+
import { extractMergeActionIdentityFromGateEvent } from "./merge-ledger.js";
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// reconcileEpic
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Execute the deterministic observed→desired reconciliation pass. All I/O is
|
|
22
|
+
* behind injected seams; the ready-set is computed by pure code (no LLM).
|
|
23
|
+
*/
|
|
24
|
+
export async function reconcileEpic(access, observed, plan, deps) {
|
|
25
|
+
const result = {
|
|
26
|
+
signals_folded: 0,
|
|
27
|
+
dispatched: 0,
|
|
28
|
+
merges_actioned: 0,
|
|
29
|
+
warnings: [],
|
|
30
|
+
};
|
|
31
|
+
const escalate = deps.escalateOnce ?? (async () => undefined);
|
|
32
|
+
// Step 1: Fold terminal signals → CAS into Postgres
|
|
33
|
+
for (const signal of observed.unfolded_terminal_signals) {
|
|
34
|
+
let casResult;
|
|
35
|
+
try {
|
|
36
|
+
casResult = await deps.casTicketStatus(observed.epic_key, signal.ticket_key, signal.postgres_row_version, signal.next_status, observed.plan_version);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "cas error";
|
|
40
|
+
result.warnings.push(`cas-error folding ${signal.signal_type} for ${signal.ticket_key}: ${safeMsg}`);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (casResult.ok) {
|
|
44
|
+
result.signals_folded += 1;
|
|
45
|
+
deps.log(`[epic-reconcile] folded ${signal.signal_type} for ${signal.ticket_key} → ${signal.next_status}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// CAS conflict: another tick already advanced this ticket — non-fatal
|
|
49
|
+
result.warnings.push(`cas-conflict folding ${signal.signal_type} for ${signal.ticket_key}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Step 1.5: Seed planned status rows for every plan node (idempotent — ON CONFLICT DO NOTHING)
|
|
53
|
+
for (const ticket of plan.tickets) {
|
|
54
|
+
try {
|
|
55
|
+
await deps.seedTicketStatus(observed.epic_key, ticket.ticket_key, plan.plan_version);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "seed error";
|
|
59
|
+
result.warnings.push(`seed-error for ${ticket.ticket_key}: ${safeMsg}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Step 2: Compute the ready-set (pure — never calls LLM)
|
|
63
|
+
const readySet = computeReadySet(plan, observed.ticket_statuses);
|
|
64
|
+
// Step 3: Dispatch each ready ticket idempotently
|
|
65
|
+
for (const ticketKey of readySet) {
|
|
66
|
+
let claimResult;
|
|
67
|
+
try {
|
|
68
|
+
claimResult = await deps.claimDispatchKey(observed.epic_key, ticketKey, observed.plan_version);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "claim error";
|
|
72
|
+
result.warnings.push(`claim-error for ${ticketKey}: ${safeMsg}`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!claimResult.ok) {
|
|
76
|
+
// lease-held: another tick is dispatching this ticket concurrently
|
|
77
|
+
result.warnings.push(`dispatch-key lease-held for ${ticketKey}`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (claimResult.kind === "terminal") {
|
|
81
|
+
// Already dispatched and terminal — nothing to do
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (claimResult.kind === "already-spawned") {
|
|
85
|
+
// Spawn already occurred; ensure post-action wait is scheduled
|
|
86
|
+
await deps.postActionWaitSeam(observed.epic_key, ticketKey);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (claimResult.kind === "already-exists") {
|
|
90
|
+
if (claimResult.dispatch.run_id === null) {
|
|
91
|
+
// Spawn happened on a prior tick but correlateRunId failed — the live run's
|
|
92
|
+
// terminal signals can never be correlated back to this ticket. Escalate so
|
|
93
|
+
// an operator can manually recover (set run_id or abandon the dispatch key).
|
|
94
|
+
result.warnings.push(`dispatch-orphan: ${ticketKey} has pending dispatch key with no run_id`);
|
|
95
|
+
await escalate(observed.epic_key, `dispatch-orphan:${ticketKey}`);
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
// kind === "claimed": proceed with spawn
|
|
100
|
+
const dispatchKey = claimResult.dispatch.dispatch_key;
|
|
101
|
+
let runId;
|
|
102
|
+
try {
|
|
103
|
+
runId = await deps.dispatchSeam(observed.epic_key, ticketKey);
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "dispatch error";
|
|
107
|
+
result.warnings.push(`dispatch-failed for ${ticketKey}: ${safeMsg}`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
await deps.correlateRunId(dispatchKey, runId);
|
|
112
|
+
result.dispatched += 1;
|
|
113
|
+
deps.log(`[epic-reconcile] dispatched ${ticketKey} run_id=${runId}`);
|
|
114
|
+
await deps.postActionWaitSeam(observed.epic_key, ticketKey);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "correlate error";
|
|
118
|
+
result.warnings.push(`correlate-failed for ${ticketKey}: ${safeMsg}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Step 4: Action approved merges via C6 delegation
|
|
122
|
+
for (const event of observed.pending_merge_events) {
|
|
123
|
+
const identity = extractMergeActionIdentityFromGateEvent(event);
|
|
124
|
+
if (!identity)
|
|
125
|
+
continue;
|
|
126
|
+
try {
|
|
127
|
+
const mergeResult = await deps.processMerge(access, event);
|
|
128
|
+
if (mergeResult.processed) {
|
|
129
|
+
result.merges_actioned += 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
const safeMsg = err instanceof Error ? err.constructor.name : "merge error";
|
|
134
|
+
result.warnings.push(`merge-failed ${identity.action_key}: ${safeMsg}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Step 5: Post-action waits are scheduled inline above per-dispatch
|
|
138
|
+
return result;
|
|
139
|
+
}
|