ralph-hero-mcp-server 2.4.16 → 2.4.17
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/tools/sync-tools.js +60 -0
- package/package.json +1 -1
package/dist/tools/sync-tools.js
CHANGED
|
@@ -57,6 +57,47 @@ const UPDATE_FIELD_MUTATION = `mutation($projectId: ID!, $itemId: ID!, $fieldId:
|
|
|
57
57
|
projectV2Item { id }
|
|
58
58
|
}
|
|
59
59
|
}`;
|
|
60
|
+
const ADD_SYNC_AUDIT_COMMENT = `mutation($subjectId: ID!, $body: String!) {
|
|
61
|
+
addComment(input: { subjectId: $subjectId, body: $body }) {
|
|
62
|
+
commentEdge { node { id } }
|
|
63
|
+
}
|
|
64
|
+
}`;
|
|
65
|
+
const SYNC_AUDIT_MARKER = "<!-- cross-project-sync-audit -->";
|
|
66
|
+
const ISSUE_COMMENTS_QUERY = `query($issueId: ID!) {
|
|
67
|
+
node(id: $issueId) {
|
|
68
|
+
... on Issue {
|
|
69
|
+
comments(last: 20) { nodes { body } }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}`;
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Audit trail helpers (#199)
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
/**
|
|
77
|
+
* Build the audit comment body for a cross-project sync operation.
|
|
78
|
+
* Pure function, no I/O.
|
|
79
|
+
*/
|
|
80
|
+
export function buildSyncAuditBody(workflowState, syncedResults) {
|
|
81
|
+
const lines = syncedResults.map((r) => `- Project #${r.projectNumber} (${r.currentState ?? "none"} -> ${workflowState})`);
|
|
82
|
+
return (`${SYNC_AUDIT_MARKER}\n` +
|
|
83
|
+
`**Cross-project sync** \u2014 Workflow State synced to **${workflowState}** across ${syncedResults.length} project(s):\n` +
|
|
84
|
+
lines.join("\n"));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Detect if any comment bodies contain the sync audit marker.
|
|
88
|
+
* Pure function for testability.
|
|
89
|
+
*/
|
|
90
|
+
export function detectSyncAuditMarker(comments) {
|
|
91
|
+
return comments.some((c) => c.body.startsWith(SYNC_AUDIT_MARKER));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if an issue already has a sync audit comment.
|
|
95
|
+
*/
|
|
96
|
+
async function hasExistingSyncAuditComment(client, issueNodeId) {
|
|
97
|
+
const result = await client.query(ISSUE_COMMENTS_QUERY, { issueId: issueNodeId });
|
|
98
|
+
const comments = result.node?.comments?.nodes ?? [];
|
|
99
|
+
return detectSyncAuditMarker(comments);
|
|
100
|
+
}
|
|
60
101
|
// ---------------------------------------------------------------------------
|
|
61
102
|
// Helpers
|
|
62
103
|
// ---------------------------------------------------------------------------
|
|
@@ -88,6 +129,11 @@ export function registerSyncTools(server, client, _fieldCache) {
|
|
|
88
129
|
.optional()
|
|
89
130
|
.default(false)
|
|
90
131
|
.describe("If true, return affected projects without mutating (default: false)"),
|
|
132
|
+
auditComment: z
|
|
133
|
+
.boolean()
|
|
134
|
+
.optional()
|
|
135
|
+
.default(true)
|
|
136
|
+
.describe("Add audit comment to the issue after sync (default: true)"),
|
|
91
137
|
}, async (args) => {
|
|
92
138
|
try {
|
|
93
139
|
const { owner, repo } = resolveConfig(client, args);
|
|
@@ -164,6 +210,19 @@ export function registerSyncTools(server, client, _fieldCache) {
|
|
|
164
210
|
targetState: args.workflowState,
|
|
165
211
|
});
|
|
166
212
|
}
|
|
213
|
+
// Audit trail: add comment documenting the sync (#199)
|
|
214
|
+
let auditCommentAdded = false;
|
|
215
|
+
if (args.auditComment && !args.dryRun && synced.length > 0) {
|
|
216
|
+
const alreadyAudited = await hasExistingSyncAuditComment(client, issueNodeId);
|
|
217
|
+
if (!alreadyAudited) {
|
|
218
|
+
const body = buildSyncAuditBody(args.workflowState, synced);
|
|
219
|
+
await client.mutate(ADD_SYNC_AUDIT_COMMENT, {
|
|
220
|
+
subjectId: issueNodeId,
|
|
221
|
+
body,
|
|
222
|
+
});
|
|
223
|
+
auditCommentAdded = true;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
167
226
|
return toolSuccess({
|
|
168
227
|
number: args.number,
|
|
169
228
|
workflowState: args.workflowState,
|
|
@@ -172,6 +231,7 @@ export function registerSyncTools(server, client, _fieldCache) {
|
|
|
172
231
|
skippedCount: skipped.length,
|
|
173
232
|
synced,
|
|
174
233
|
skipped,
|
|
234
|
+
auditCommentAdded,
|
|
175
235
|
});
|
|
176
236
|
}
|
|
177
237
|
catch (error) {
|