@taiga-ai/mcp-server 0.25.0-dev.469 → 0.25.0-dev.470
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/index.js
CHANGED
|
@@ -3741,6 +3741,22 @@ function runOutcome(run) {
|
|
|
3741
3741
|
};
|
|
3742
3742
|
}
|
|
3743
3743
|
/**
|
|
3744
|
+
* What hardening left blocking, in a sentence: the findings the run names (PRO-2817), or, for a run reported before
|
|
3745
|
+
* it recorded them, how many.
|
|
3746
|
+
*/
|
|
3747
|
+
function hardeningSaid(blocking, named) {
|
|
3748
|
+
const count = `Hardening ended with ${blocking} blocking finding${blocking === 1 ? "" : "s"} it could not fix`;
|
|
3749
|
+
if (named.length === 0) return `${count}; the run records how many, not which.`;
|
|
3750
|
+
const shown = named.slice(0, 3).map((finding) => {
|
|
3751
|
+
const message = String(finding["message"]);
|
|
3752
|
+
const where = finding["line"] ? `${String(finding["path"])}:${String(finding["line"])}` : String(finding["path"]);
|
|
3753
|
+
return `${message} (${String(finding["tool"])}, ${where})`;
|
|
3754
|
+
});
|
|
3755
|
+
const rest = blocking - shown.length;
|
|
3756
|
+
const recorded = named.length > shown.length ? `, ${named.length} recorded in taiga_get_run` : "";
|
|
3757
|
+
return `${count}: ${shown.join("; ")}${rest > 0 ? `; and ${rest} more${recorded}` : ""}.`;
|
|
3758
|
+
}
|
|
3759
|
+
/**
|
|
3744
3760
|
* What each failedReason means for the next move (PRO-2800): reviewers met dispatch_rejected and agent_reported as
|
|
3745
3761
|
* bare enums. As @taiga/types documents them.
|
|
3746
3762
|
*/
|
|
@@ -3765,10 +3781,11 @@ function readableRun(run, opts = {}) {
|
|
|
3765
3781
|
const means = FAILED_REASON_MEANS[String(run["failedReason"])];
|
|
3766
3782
|
const hardening = run["hardeningResult"];
|
|
3767
3783
|
const blocking = typeof hardening?.blockingFindings === "number" ? hardening.blockingFindings : 0;
|
|
3784
|
+
const named = Array.isArray(hardening?.blocking) ? hardening.blocking : [];
|
|
3768
3785
|
return {
|
|
3769
3786
|
...rest,
|
|
3770
3787
|
...means ? { failedReasonMeans: means } : {},
|
|
3771
|
-
...blocking > 0 ? { hardeningNote:
|
|
3788
|
+
...blocking > 0 ? { hardeningNote: hardeningSaid(blocking, named) } : {},
|
|
3772
3789
|
...opts.row || error === void 0 ? {} : { error },
|
|
3773
3790
|
...opts.row || reviewEscalation === void 0 ? {} : { reviewEscalation },
|
|
3774
3791
|
...typeof rest["prNumber"] === "number" || rest["prUrl"] ? { prDraft } : {},
|
package/package.json
CHANGED
|
@@ -8950,6 +8950,78 @@ describe('what the seventh agent review found (PRO-2800)', () => {
|
|
|
8950
8950
|
expect(bundle.runs[0]).not.toHaveProperty('hardeningResult');
|
|
8951
8951
|
});
|
|
8952
8952
|
|
|
8953
|
+
it('names the blocking hardening findings a run recorded', async () => {
|
|
8954
|
+
const { client } = await bootMcpPair({
|
|
8955
|
+
capabilities: ['products:read'],
|
|
8956
|
+
routes: {
|
|
8957
|
+
[`/v1/builds/${BUILD_ID}/steps`]: { data: [] },
|
|
8958
|
+
[`/v1/builds/${BUILD_ID}`]: {
|
|
8959
|
+
data: {
|
|
8960
|
+
id: BUILD_ID,
|
|
8961
|
+
productId: PRODUCT_ID,
|
|
8962
|
+
status: 'needs_review',
|
|
8963
|
+
prNumber: 4,
|
|
8964
|
+
hardeningResult: {
|
|
8965
|
+
passed: false,
|
|
8966
|
+
scanners: {},
|
|
8967
|
+
blockingFindings: 1,
|
|
8968
|
+
blocking: [
|
|
8969
|
+
{
|
|
8970
|
+
tool: 'betterleaks',
|
|
8971
|
+
severity: 'critical',
|
|
8972
|
+
path: 'src/config.rs',
|
|
8973
|
+
line: 12,
|
|
8974
|
+
message: 'generic-api-key: Hardcoded API key',
|
|
8975
|
+
},
|
|
8976
|
+
],
|
|
8977
|
+
},
|
|
8978
|
+
},
|
|
8979
|
+
},
|
|
8980
|
+
},
|
|
8981
|
+
});
|
|
8982
|
+
|
|
8983
|
+
const run = parseToolResult(await client.callTool({ name: 'taiga_get_run', arguments: { runId: BUILD_ID } }));
|
|
8984
|
+
|
|
8985
|
+
expect(run.hardeningNote).toBe(
|
|
8986
|
+
'Hardening ended with 1 blocking finding it could not fix: generic-api-key: Hardcoded API key (betterleaks, src/config.rs:12).'
|
|
8987
|
+
);
|
|
8988
|
+
});
|
|
8989
|
+
|
|
8990
|
+
it('always says where a blocking finding is, even when its title names the path', async () => {
|
|
8991
|
+
const { client } = await bootMcpPair({
|
|
8992
|
+
capabilities: ['products:read'],
|
|
8993
|
+
routes: {
|
|
8994
|
+
[`/v1/builds/${BUILD_ID}/steps`]: { data: [] },
|
|
8995
|
+
[`/v1/builds/${BUILD_ID}`]: {
|
|
8996
|
+
data: {
|
|
8997
|
+
id: BUILD_ID,
|
|
8998
|
+
productId: PRODUCT_ID,
|
|
8999
|
+
status: 'needs_review',
|
|
9000
|
+
hardeningResult: {
|
|
9001
|
+
passed: false,
|
|
9002
|
+
blockingFindings: 1,
|
|
9003
|
+
blocking: [
|
|
9004
|
+
{
|
|
9005
|
+
tool: 'betterleaks',
|
|
9006
|
+
severity: 'critical',
|
|
9007
|
+
path: 'src/config.rs',
|
|
9008
|
+
line: 12,
|
|
9009
|
+
message: 'aws-key: AWS key in src/config.rs',
|
|
9010
|
+
},
|
|
9011
|
+
],
|
|
9012
|
+
},
|
|
9013
|
+
},
|
|
9014
|
+
},
|
|
9015
|
+
},
|
|
9016
|
+
});
|
|
9017
|
+
|
|
9018
|
+
const run = parseToolResult(await client.callTool({ name: 'taiga_get_run', arguments: { runId: BUILD_ID } }));
|
|
9019
|
+
|
|
9020
|
+
expect(run.hardeningNote).toBe(
|
|
9021
|
+
'Hardening ended with 1 blocking finding it could not fix: aws-key: AWS key in src/config.rs (betterleaks, src/config.rs:12).'
|
|
9022
|
+
);
|
|
9023
|
+
});
|
|
9024
|
+
|
|
8953
9025
|
it('says what the API says when it names the product holding a repository', async () => {
|
|
8954
9026
|
const { client, fetchSpy } = await bootMcpPair({
|
|
8955
9027
|
capabilities: ALL_CAPABILITIES,
|
package/src/tools/builds.ts
CHANGED
|
@@ -222,6 +222,24 @@ export function runOutcome(run: Record<string, unknown>): { disposition: string;
|
|
|
222
222
|
return { disposition, outcome: sentence[disposition] ?? status };
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
/**
|
|
226
|
+
* What hardening left blocking, in a sentence: the findings the run names (PRO-2817), or, for a run reported before
|
|
227
|
+
* it recorded them, how many.
|
|
228
|
+
*/
|
|
229
|
+
function hardeningSaid(blocking: number, named: Record<string, unknown>[]): string {
|
|
230
|
+
const count = `Hardening ended with ${blocking} blocking finding${blocking === 1 ? '' : 's'} it could not fix`;
|
|
231
|
+
if (named.length === 0) return `${count}; the run records how many, not which.`;
|
|
232
|
+
const shown = named.slice(0, 3).map((finding) => {
|
|
233
|
+
const message = String(finding['message']);
|
|
234
|
+
const where = finding['line'] ? `${String(finding['path'])}:${String(finding['line'])}` : String(finding['path']);
|
|
235
|
+
// Always where it is, though a scanner's title may repeat the path: a substring test would drop a real one.
|
|
236
|
+
return `${message} (${String(finding['tool'])}, ${where})`;
|
|
237
|
+
});
|
|
238
|
+
const rest = blocking - shown.length;
|
|
239
|
+
const recorded = named.length > shown.length ? `, ${named.length} recorded in taiga_get_run` : '';
|
|
240
|
+
return `${count}: ${shown.join('; ')}${rest > 0 ? `; and ${rest} more${recorded}` : ''}.`;
|
|
241
|
+
}
|
|
242
|
+
|
|
225
243
|
/**
|
|
226
244
|
* What each failedReason means for the next move (PRO-2800): reviewers met dispatch_rejected and agent_reported as
|
|
227
245
|
* bare enums. As @taiga/types documents them.
|
|
@@ -247,14 +265,15 @@ export function readableRun(run: Record<string, unknown>, opts: { row?: boolean
|
|
|
247
265
|
const { prDraft, error, reviewEscalation, runtime: _runtime, ...rest } = run;
|
|
248
266
|
const said = runOutcome(run);
|
|
249
267
|
const means = FAILED_REASON_MEANS[String(run['failedReason'])];
|
|
250
|
-
const hardening = run['hardeningResult'] as { blockingFindings?: unknown } | null | undefined;
|
|
268
|
+
const hardening = run['hardeningResult'] as { blockingFindings?: unknown; blocking?: unknown } | null | undefined;
|
|
251
269
|
const blocking = typeof hardening?.blockingFindings === 'number' ? hardening.blockingFindings : 0;
|
|
270
|
+
const named = Array.isArray(hardening?.blocking) ? (hardening.blocking as Record<string, unknown>[]) : [];
|
|
252
271
|
return {
|
|
253
272
|
...rest,
|
|
254
273
|
...(means ? { failedReasonMeans: means } : {}),
|
|
255
274
|
...(blocking > 0
|
|
256
275
|
? {
|
|
257
|
-
hardeningNote:
|
|
276
|
+
hardeningNote: hardeningSaid(blocking, named),
|
|
258
277
|
}
|
|
259
278
|
: {}),
|
|
260
279
|
// A row's outcome says the error and the handback; the full read keeps them whole.
|
|
Binary file
|
|
Binary file
|