@codazen/harmonica-mcp 3.9.0 → 3.9.1
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 +122 -140
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21542,18 +21542,18 @@ async function validateAuth(client, orgIdentifier, isOrgSlug, userId) {
|
|
|
21542
21542
|
}
|
|
21543
21543
|
|
|
21544
21544
|
// ../../libs/harmonica-services/src/mcp/org-guard.ts
|
|
21545
|
-
async function
|
|
21546
|
-
const
|
|
21547
|
-
if (!
|
|
21545
|
+
async function assertSystemInOrg(client, systemId, orgId) {
|
|
21546
|
+
const system = await client.getSystem(systemId);
|
|
21547
|
+
if (!system) {
|
|
21548
21548
|
throw new Error(`System not found: "${systemId}"`);
|
|
21549
21549
|
}
|
|
21550
|
-
if (
|
|
21550
|
+
if (system.orgId !== orgId) {
|
|
21551
21551
|
throw new Error(
|
|
21552
21552
|
`System "${systemId}" does not belong to the configured organization. Access denied.`
|
|
21553
21553
|
);
|
|
21554
21554
|
}
|
|
21555
21555
|
}
|
|
21556
|
-
async function
|
|
21556
|
+
async function assertRevisionInSystem(client, revisionId, systemId) {
|
|
21557
21557
|
const revision = await client.getRevision(revisionId);
|
|
21558
21558
|
if (!revision) {
|
|
21559
21559
|
throw new Error(`Revision not found: "${revisionId}"`);
|
|
@@ -21575,18 +21575,6 @@ async function assertBeatInOrg(client, beatId, orgId) {
|
|
|
21575
21575
|
);
|
|
21576
21576
|
}
|
|
21577
21577
|
}
|
|
21578
|
-
async function fetchProjectInOrg(client, systemId, orgId) {
|
|
21579
|
-
const project = await client.getSystem(systemId);
|
|
21580
|
-
if (!project) {
|
|
21581
|
-
throw new Error(`System not found: "${systemId}"`);
|
|
21582
|
-
}
|
|
21583
|
-
if (project.orgId !== orgId) {
|
|
21584
|
-
throw new Error(
|
|
21585
|
-
`System "${systemId}" does not belong to the configured organization. Access denied.`
|
|
21586
|
-
);
|
|
21587
|
-
}
|
|
21588
|
-
return project;
|
|
21589
|
-
}
|
|
21590
21578
|
async function fetchSystemInOrg(client, systemId, orgId) {
|
|
21591
21579
|
const system = await client.getSystem(systemId);
|
|
21592
21580
|
if (!system) {
|
|
@@ -21979,7 +21967,7 @@ function registerActivityTools(server, ctx, client) {
|
|
|
21979
21967
|
importance: external_exports.enum(IMPORTANCE_VALUES).optional().describe("Filter by minimum importance level")
|
|
21980
21968
|
},
|
|
21981
21969
|
async ({ systemId, limit, importance }) => {
|
|
21982
|
-
await
|
|
21970
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
21983
21971
|
const { entries, hasMore } = await client.listSystemActivities(systemId, {
|
|
21984
21972
|
limit: limit ?? 30,
|
|
21985
21973
|
minImportance: importance
|
|
@@ -22011,7 +21999,7 @@ function registerAnalysisTools(server, ctx, client) {
|
|
|
22011
21999
|
minClusterSize: external_exports.coerce.number().int().min(2).optional().default(3).describe("Minimum cluster size. Default 3")
|
|
22012
22000
|
},
|
|
22013
22001
|
async ({ systemId, entityType, threshold, minClusterSize }) => {
|
|
22014
|
-
await
|
|
22002
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22015
22003
|
const result = await client.clusterEntities(systemId, entityType, { threshold, minClusterSize });
|
|
22016
22004
|
if (result.clusters.length === 0) {
|
|
22017
22005
|
return {
|
|
@@ -22043,7 +22031,7 @@ Analyzed: ${result.totalAnalyzed} | Clusters: ${result.clusters.length} | Noise:
|
|
|
22043
22031
|
minClusterSize: external_exports.coerce.number().int().min(2).optional().default(2).describe("Minimum cluster size. Default 2")
|
|
22044
22032
|
},
|
|
22045
22033
|
async ({ systemId, analysisType, entityType, threshold, minClusterSize }) => {
|
|
22046
|
-
await
|
|
22034
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22047
22035
|
const result = await client.runClusteredAnalysis(systemId, analysisType, {
|
|
22048
22036
|
entityType,
|
|
22049
22037
|
threshold,
|
|
@@ -22078,7 +22066,7 @@ function registerAuditIntegrityTools(server, ctx, client) {
|
|
|
22078
22066
|
},
|
|
22079
22067
|
async ({ systemId, limit }) => {
|
|
22080
22068
|
try {
|
|
22081
|
-
await
|
|
22069
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22082
22070
|
const report = await client.verifyAuditIntegrity(systemId, { limit });
|
|
22083
22071
|
const lines = [
|
|
22084
22072
|
`## Audit Integrity Report`,
|
|
@@ -22207,7 +22195,7 @@ function registerBaselineTools(server, ctx, client) {
|
|
|
22207
22195
|
},
|
|
22208
22196
|
async ({ systemId, beatIds, runChecks, localPath }) => {
|
|
22209
22197
|
try {
|
|
22210
|
-
await
|
|
22198
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22211
22199
|
const task = await client.baselineSystem(systemId, { beatIds, runChecks, localPath });
|
|
22212
22200
|
return {
|
|
22213
22201
|
content: [{
|
|
@@ -22296,7 +22284,7 @@ Rationale: ${rationale}`;
|
|
|
22296
22284
|
},
|
|
22297
22285
|
async ({ systemId, items, reason }) => {
|
|
22298
22286
|
try {
|
|
22299
|
-
await
|
|
22287
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22300
22288
|
const result = await client.bulkReassignRevisions(items, reason, ctx.user.userId);
|
|
22301
22289
|
const lines = [
|
|
22302
22290
|
`# Bulk reassignment complete: ${result.reassigned.length} succeeded, ${result.failed.length} failed`,
|
|
@@ -22335,7 +22323,7 @@ Rationale: ${rationale}`;
|
|
|
22335
22323
|
},
|
|
22336
22324
|
async ({ systemId, revisionId, toBeatId, reason }) => {
|
|
22337
22325
|
try {
|
|
22338
|
-
await
|
|
22326
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
22339
22327
|
const result = await client.reassignRevision(revisionId, toBeatId, reason, ctx.user.userId);
|
|
22340
22328
|
const text = [
|
|
22341
22329
|
`Revision reassigned successfully.`,
|
|
@@ -23103,7 +23091,7 @@ function registerBeatTools(server, ctx, client) {
|
|
|
23103
23091
|
includeArchived: external_exports.boolean().optional().default(false).describe("Include archived and deprecated beats (excluded by default)")
|
|
23104
23092
|
},
|
|
23105
23093
|
async ({ systemId, offset = 0, limit = 100, includeArchived }) => {
|
|
23106
|
-
await
|
|
23094
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
23107
23095
|
let beats = await client.listSystemBeats(systemId);
|
|
23108
23096
|
if (!includeArchived) {
|
|
23109
23097
|
beats = beats.filter((b) => b.beatStatus !== "archived");
|
|
@@ -23169,7 +23157,7 @@ function registerBeatTools(server, ctx, client) {
|
|
|
23169
23157
|
},
|
|
23170
23158
|
async ({ systemId, title, description, tags, priority, estimatedEffort, beatId, humanAssignee, agentAssignee, branch }) => {
|
|
23171
23159
|
try {
|
|
23172
|
-
await
|
|
23160
|
+
await fetchSystemInOrg(client, systemId, ctx.orgId);
|
|
23173
23161
|
const resolvedBeatId = beatId ?? await client.getNextBeatId(systemId);
|
|
23174
23162
|
const beat = await client.createBeat({
|
|
23175
23163
|
beatId: resolvedBeatId,
|
|
@@ -23286,7 +23274,7 @@ ${formatBeatDetail(beat)}${similarityWarning}` }] };
|
|
|
23286
23274
|
},
|
|
23287
23275
|
async ({ systemId, beatId, status, includeArchived }) => {
|
|
23288
23276
|
try {
|
|
23289
|
-
await
|
|
23277
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
23290
23278
|
const revisions = beatId ? await client.listBeatRevisions(systemId, beatId, { status, includeArchived }) : await client.listSystemRevisions(systemId, { status, includeArchived });
|
|
23291
23279
|
return { content: [{ type: "text", text: formatRevisionSummaryTable(revisions) }] };
|
|
23292
23280
|
} catch (err) {
|
|
@@ -23972,7 +23960,7 @@ function registerCheckTools(server, ctx, client) {
|
|
|
23972
23960
|
},
|
|
23973
23961
|
async ({ checkType, targetId, systemId, branch, localPath }) => {
|
|
23974
23962
|
try {
|
|
23975
|
-
await
|
|
23963
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
23976
23964
|
const targetError = checkType === "build_quality" ? buildQualityTargetError(targetId) : checkType === "beat_version_quality" || checkType === "plan_quality" ? beatVersionQualityTargetError(targetId) : null;
|
|
23977
23965
|
if (targetError) {
|
|
23978
23966
|
return { content: [{ type: "text", text: targetError }], isError: true };
|
|
@@ -24560,7 +24548,7 @@ function registerDropQualityTools(server, ctx, client) {
|
|
|
24560
24548
|
},
|
|
24561
24549
|
async ({ dropId, systemId, wait }) => {
|
|
24562
24550
|
try {
|
|
24563
|
-
await
|
|
24551
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
24564
24552
|
const drop = await client.getDrop(dropId);
|
|
24565
24553
|
if (!drop) {
|
|
24566
24554
|
return { content: [{ type: "text", text: `Drop "${dropId}" not found.` }], isError: true };
|
|
@@ -24954,8 +24942,8 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
24954
24942
|
systemId: external_exports.string().describe("The system ID to embed entities for")
|
|
24955
24943
|
},
|
|
24956
24944
|
async ({ systemId }) => {
|
|
24957
|
-
await
|
|
24958
|
-
const result = await client.
|
|
24945
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
24946
|
+
const result = await client.embedSystemEntities(systemId);
|
|
24959
24947
|
const text = `## Embedding Results
|
|
24960
24948
|
|
|
24961
24949
|
- Embedded: ${result.embedded}
|
|
@@ -24986,7 +24974,7 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
24986
24974
|
}
|
|
24987
24975
|
let scope;
|
|
24988
24976
|
if (systemId) {
|
|
24989
|
-
await
|
|
24977
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
24990
24978
|
scope = { systemId };
|
|
24991
24979
|
} else if (teamspaceId) {
|
|
24992
24980
|
await assertTeamspaceInOrg(client, teamspaceId, ctx.orgId);
|
|
@@ -25012,7 +25000,7 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
25012
25000
|
beatId: external_exports.string().optional().describe("Restrict results to notes belonging to a specific beat (DynamoDB post-filter)")
|
|
25013
25001
|
},
|
|
25014
25002
|
async ({ noteId, systemId, threshold, limit, includeArchived = false, noteStatus, beatId }) => {
|
|
25015
|
-
await
|
|
25003
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25016
25004
|
const ids = Array.isArray(noteId) ? noteId : [noteId];
|
|
25017
25005
|
if (ids.length === 1) {
|
|
25018
25006
|
const results = await client.findSimilarNotes(ids[0], systemId, { threshold, limit, includeArchived, noteStatus, beatId });
|
|
@@ -25053,7 +25041,7 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
25053
25041
|
limit: external_exports.coerce.number().int().min(1).max(50).optional().default(10).describe("Max results to return. Default 10")
|
|
25054
25042
|
},
|
|
25055
25043
|
async ({ noteId, systemId, threshold, limit }) => {
|
|
25056
|
-
await
|
|
25044
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25057
25045
|
const results = await client.findRelatedBeats(noteId, systemId, { threshold, limit });
|
|
25058
25046
|
const text = formatSimilarityResults(results, noteId, "Related Beats");
|
|
25059
25047
|
return { content: [{ type: "text", text }] };
|
|
@@ -25069,7 +25057,7 @@ function registerEmbeddingTools(server, ctx, client) {
|
|
|
25069
25057
|
includeLinked: external_exports.coerce.boolean().optional().default(false).describe("Include notes that already have dependsOnNotes links. Default false (excludes them). Set true for thematic grouping pass.")
|
|
25070
25058
|
},
|
|
25071
25059
|
async ({ systemId, threshold, minClusterSize, includeLinked }) => {
|
|
25072
|
-
await
|
|
25060
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25073
25061
|
const result = await client.clusterNotes(systemId, { threshold, minClusterSize, excludeAlreadyLinked: !includeLinked });
|
|
25074
25062
|
if (result.clusters.length === 0) {
|
|
25075
25063
|
return { content: [{ type: "text", text: `No clusters found among ${result.totalAnalyzed} analyzed notes. Try lowering the threshold.` }] };
|
|
@@ -25100,7 +25088,7 @@ ${members}`;
|
|
|
25100
25088
|
includeLinked: external_exports.coerce.boolean().optional().default(false).describe("Include notes that already have dependsOnNotes links. Default false.")
|
|
25101
25089
|
},
|
|
25102
25090
|
async ({ systemId, threshold, minClusterSize, includeLinked }) => {
|
|
25103
|
-
await
|
|
25091
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25104
25092
|
const result = await client.consolidateNotes(systemId, { threshold, minClusterSize, includeLinked });
|
|
25105
25093
|
if (result.proposals.length === 0) {
|
|
25106
25094
|
return { content: [{ type: "text", text: `No consolidation candidates found among ${result.totalAnalyzed} analyzed notes.` }] };
|
|
@@ -25341,7 +25329,7 @@ function registerLayerTools(server, ctx, client) {
|
|
|
25341
25329
|
},
|
|
25342
25330
|
async ({ systemId }) => {
|
|
25343
25331
|
try {
|
|
25344
|
-
await
|
|
25332
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25345
25333
|
} catch (err) {
|
|
25346
25334
|
const message = err instanceof Error ? err.message : String(err);
|
|
25347
25335
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -25366,7 +25354,7 @@ function registerLayerTools(server, ctx, client) {
|
|
|
25366
25354
|
},
|
|
25367
25355
|
async ({ systemId, layerId }) => {
|
|
25368
25356
|
try {
|
|
25369
|
-
await
|
|
25357
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25370
25358
|
} catch (err) {
|
|
25371
25359
|
const message = err instanceof Error ? err.message : String(err);
|
|
25372
25360
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -25401,7 +25389,7 @@ function registerLayerTools(server, ctx, client) {
|
|
|
25401
25389
|
},
|
|
25402
25390
|
async ({ systemId, layerKey, name, description, parentLayerId, repoPatterns }) => {
|
|
25403
25391
|
try {
|
|
25404
|
-
await
|
|
25392
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25405
25393
|
} catch (err) {
|
|
25406
25394
|
const message = err instanceof Error ? err.message : String(err);
|
|
25407
25395
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -25440,7 +25428,7 @@ ${formatLayerDetail(layer)}` }] };
|
|
|
25440
25428
|
},
|
|
25441
25429
|
async ({ systemId, layerId, name, description, repoPatterns }) => {
|
|
25442
25430
|
try {
|
|
25443
|
-
await
|
|
25431
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25444
25432
|
} catch (err) {
|
|
25445
25433
|
const message = err instanceof Error ? err.message : String(err);
|
|
25446
25434
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -25484,7 +25472,7 @@ ${formatLayerDetail(layer)}` }] };
|
|
|
25484
25472
|
},
|
|
25485
25473
|
async ({ systemId, layerId, status, reason }) => {
|
|
25486
25474
|
try {
|
|
25487
|
-
await
|
|
25475
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25488
25476
|
} catch (err) {
|
|
25489
25477
|
const message = err instanceof Error ? err.message : String(err);
|
|
25490
25478
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -25828,7 +25816,7 @@ function registerNextActionsTools(server, ctx, client) {
|
|
|
25828
25816
|
},
|
|
25829
25817
|
async ({ systemId, limit }) => {
|
|
25830
25818
|
try {
|
|
25831
|
-
await
|
|
25819
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25832
25820
|
const actions = await client.getNextActions(systemId, { limit });
|
|
25833
25821
|
return { content: [{ type: "text", text: formatNextActions(actions) }] };
|
|
25834
25822
|
} catch (err) {
|
|
@@ -25845,7 +25833,7 @@ function registerNextActionsTools(server, ctx, client) {
|
|
|
25845
25833
|
},
|
|
25846
25834
|
async ({ systemId }) => {
|
|
25847
25835
|
try {
|
|
25848
|
-
await
|
|
25836
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25849
25837
|
const actions = await client.listTriageActions(systemId);
|
|
25850
25838
|
return { content: [{ type: "text", text: formatTriageActions(actions) }] };
|
|
25851
25839
|
} catch (err) {
|
|
@@ -25863,7 +25851,7 @@ function registerNextActionsTools(server, ctx, client) {
|
|
|
25863
25851
|
},
|
|
25864
25852
|
async ({ systemId, actionKey }) => {
|
|
25865
25853
|
try {
|
|
25866
|
-
await
|
|
25854
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
25867
25855
|
await client.dismissTriageAction(systemId, actionKey, ctx.user?.userId ?? "mcp");
|
|
25868
25856
|
return { content: [{ type: "text", text: `Action ${actionKey} dismissed.` }] };
|
|
25869
25857
|
} catch (err) {
|
|
@@ -26341,7 +26329,7 @@ var normalizeSystemId = (raw) => {
|
|
|
26341
26329
|
const b = raw;
|
|
26342
26330
|
const id = b["systemId"] || b["projectId"];
|
|
26343
26331
|
if (!id) return raw;
|
|
26344
|
-
return { ...b, systemId: id
|
|
26332
|
+
return { ...b, systemId: id };
|
|
26345
26333
|
};
|
|
26346
26334
|
var BeatApiSchema = external_exports.preprocess(
|
|
26347
26335
|
(raw) => {
|
|
@@ -26349,12 +26337,11 @@ var BeatApiSchema = external_exports.preprocess(
|
|
|
26349
26337
|
const b = raw;
|
|
26350
26338
|
const id = b["systemId"] || b["projectId"];
|
|
26351
26339
|
if (!id) return raw;
|
|
26352
|
-
return { ...b, systemId: id
|
|
26340
|
+
return { ...b, systemId: id };
|
|
26353
26341
|
},
|
|
26354
26342
|
external_exports.object({
|
|
26355
26343
|
beatId: external_exports.string(),
|
|
26356
26344
|
systemId: external_exports.string(),
|
|
26357
|
-
projectId: external_exports.string(),
|
|
26358
26345
|
/** Source project's title; attached by the flat /api/beats endpoint for
|
|
26359
26346
|
* multi-project (teamspace/org) responses. */
|
|
26360
26347
|
projectName: external_exports.string().nullish(),
|
|
@@ -26386,7 +26373,6 @@ var RevisionApiSchema = external_exports.preprocess(
|
|
|
26386
26373
|
revisionId: external_exports.string(),
|
|
26387
26374
|
beatId: external_exports.string(),
|
|
26388
26375
|
systemId: external_exports.string(),
|
|
26389
|
-
projectId: external_exports.string(),
|
|
26390
26376
|
status: RevisionStatusSchema,
|
|
26391
26377
|
title: external_exports.string().default(""),
|
|
26392
26378
|
versionNumber: external_exports.number(),
|
|
@@ -26413,7 +26399,6 @@ var NoteApiSchema = external_exports.preprocess(normalizeSystemId, external_expo
|
|
|
26413
26399
|
status: NoteStatusSchema,
|
|
26414
26400
|
content: external_exports.string(),
|
|
26415
26401
|
systemId: external_exports.string().nullish(),
|
|
26416
|
-
projectId: external_exports.string().nullish(),
|
|
26417
26402
|
beatId: external_exports.string().nullish(),
|
|
26418
26403
|
revisionId: external_exports.string().nullish(),
|
|
26419
26404
|
rationale: external_exports.string().nullish(),
|
|
@@ -26429,7 +26414,6 @@ var SystemApiSchema = external_exports.preprocess(
|
|
|
26429
26414
|
normalizeSystemId,
|
|
26430
26415
|
external_exports.object({
|
|
26431
26416
|
systemId: external_exports.string(),
|
|
26432
|
-
projectId: external_exports.string(),
|
|
26433
26417
|
title: external_exports.string(),
|
|
26434
26418
|
status: SystemStatusSchema,
|
|
26435
26419
|
description: external_exports.string().optional(),
|
|
@@ -26631,8 +26615,7 @@ var CheckApiSchema = external_exports.preprocess(
|
|
|
26631
26615
|
checkType: CheckTypeSchema,
|
|
26632
26616
|
targetType: CheckTargetTypeSchema,
|
|
26633
26617
|
targetId: external_exports.string(),
|
|
26634
|
-
systemId: external_exports.string()
|
|
26635
|
-
projectId: external_exports.string().optional(),
|
|
26618
|
+
systemId: external_exports.string(),
|
|
26636
26619
|
overallScore: external_exports.number(),
|
|
26637
26620
|
dimensions: external_exports.array(CheckDimensionScoreSchema),
|
|
26638
26621
|
summary: external_exports.string(),
|
|
@@ -26651,8 +26634,7 @@ var SystemCheckApiSchema = external_exports.preprocess(
|
|
|
26651
26634
|
checkType: CheckTypeSchema,
|
|
26652
26635
|
targetType: CheckTargetTypeSchema,
|
|
26653
26636
|
targetId: external_exports.string(),
|
|
26654
|
-
systemId: external_exports.string()
|
|
26655
|
-
projectId: external_exports.string().optional(),
|
|
26637
|
+
systemId: external_exports.string(),
|
|
26656
26638
|
overallScore: external_exports.number(),
|
|
26657
26639
|
summary: external_exports.string(),
|
|
26658
26640
|
triggeredBy: external_exports.string().optional(),
|
|
@@ -26712,7 +26694,6 @@ var ActivitySchema = external_exports.preprocess(
|
|
|
26712
26694
|
external_exports.object({
|
|
26713
26695
|
activityId: external_exports.string(),
|
|
26714
26696
|
systemId: external_exports.string(),
|
|
26715
|
-
projectId: external_exports.string(),
|
|
26716
26697
|
action: external_exports.string(),
|
|
26717
26698
|
importance: external_exports.enum(["minor", "moderate", "major"]),
|
|
26718
26699
|
reason: external_exports.string(),
|
|
@@ -26758,7 +26739,6 @@ var TriageActionSchema = external_exports.preprocess(
|
|
|
26758
26739
|
external_exports.object({
|
|
26759
26740
|
actionKey: external_exports.string(),
|
|
26760
26741
|
systemId: external_exports.string(),
|
|
26761
|
-
projectId: external_exports.string(),
|
|
26762
26742
|
entityId: external_exports.string().optional(),
|
|
26763
26743
|
entityType: external_exports.enum(["beat", "revision", "note"]).optional(),
|
|
26764
26744
|
beatId: external_exports.string().optional(),
|
|
@@ -26799,7 +26779,6 @@ var SearchResultSchema = external_exports.preprocess(normalizeSystemId, external
|
|
|
26799
26779
|
score: external_exports.number(),
|
|
26800
26780
|
snippet: external_exports.string(),
|
|
26801
26781
|
systemId: external_exports.string().optional(),
|
|
26802
|
-
projectId: external_exports.string().optional(),
|
|
26803
26782
|
projectName: external_exports.string().optional(),
|
|
26804
26783
|
teamspaceId: external_exports.string().optional()
|
|
26805
26784
|
}).passthrough());
|
|
@@ -26838,33 +26817,28 @@ var LandscapeMetaSchema = external_exports.object({
|
|
|
26838
26817
|
cacheHit: external_exports.boolean(),
|
|
26839
26818
|
projectionHash: external_exports.string()
|
|
26840
26819
|
}).passthrough();
|
|
26841
|
-
var LandscapeResponseSchema = external_exports.
|
|
26842
|
-
(
|
|
26843
|
-
|
|
26844
|
-
|
|
26845
|
-
|
|
26846
|
-
|
|
26847
|
-
|
|
26848
|
-
const
|
|
26849
|
-
|
|
26850
|
-
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
26855
|
-
links: external_exports.array(external_exports.object({ from: external_exports.string(), to: external_exports.string() }).passthrough()),
|
|
26856
|
-
clusters: external_exports.array(LandscapeClusterSchema),
|
|
26857
|
-
scopeBoundary: external_exports.object({
|
|
26858
|
-
systemId: external_exports.string().optional(),
|
|
26859
|
-
projectId: external_exports.string().optional(),
|
|
26820
|
+
var LandscapeResponseSchema = external_exports.object({
|
|
26821
|
+
points: external_exports.array(LandscapePointSchema),
|
|
26822
|
+
links: external_exports.array(external_exports.object({ from: external_exports.string(), to: external_exports.string() }).passthrough()),
|
|
26823
|
+
clusters: external_exports.array(LandscapeClusterSchema),
|
|
26824
|
+
scopeBoundary: external_exports.preprocess(
|
|
26825
|
+
(raw) => {
|
|
26826
|
+
if (typeof raw !== "object" || raw === null) return raw;
|
|
26827
|
+
const o = raw;
|
|
26828
|
+
const id = o["systemId"] ?? o["projectId"];
|
|
26829
|
+
if (!id) return raw;
|
|
26830
|
+
return { ...o, systemId: id };
|
|
26831
|
+
},
|
|
26832
|
+
external_exports.object({
|
|
26833
|
+
systemId: external_exports.string(),
|
|
26860
26834
|
cx: external_exports.number(),
|
|
26861
26835
|
cy: external_exports.number(),
|
|
26862
26836
|
radius: external_exports.number(),
|
|
26863
26837
|
label: external_exports.string()
|
|
26864
|
-
}).passthrough()
|
|
26865
|
-
|
|
26866
|
-
|
|
26867
|
-
);
|
|
26838
|
+
}).passthrough()
|
|
26839
|
+
).optional(),
|
|
26840
|
+
meta: LandscapeMetaSchema
|
|
26841
|
+
}).passthrough();
|
|
26868
26842
|
var ClusterDescriptionSchema = external_exports.object({
|
|
26869
26843
|
title: external_exports.string(),
|
|
26870
26844
|
description: external_exports.string()
|
|
@@ -26873,7 +26847,6 @@ var BeatVersionItemSchema = external_exports.preprocess(normalizeSystemId, exter
|
|
|
26873
26847
|
beatVersionId: external_exports.string(),
|
|
26874
26848
|
beatId: external_exports.string(),
|
|
26875
26849
|
systemId: external_exports.string().optional(),
|
|
26876
|
-
projectId: external_exports.string().optional(),
|
|
26877
26850
|
status: external_exports.string()
|
|
26878
26851
|
}).passthrough());
|
|
26879
26852
|
var BeatVersionsResponseSchema = external_exports.object({
|
|
@@ -26882,7 +26855,6 @@ var BeatVersionsResponseSchema = external_exports.object({
|
|
|
26882
26855
|
var ConversationSummaryBaseSchema = external_exports.object({
|
|
26883
26856
|
conversationId: external_exports.string(),
|
|
26884
26857
|
systemId: external_exports.string().optional(),
|
|
26885
|
-
projectId: external_exports.string().optional(),
|
|
26886
26858
|
teamspaceId: external_exports.string().optional(),
|
|
26887
26859
|
userId: external_exports.string(),
|
|
26888
26860
|
conversationType: external_exports.string(),
|
|
@@ -27001,6 +26973,13 @@ var WorkItemApiSchema = external_exports.object({
|
|
|
27001
26973
|
costPerValueUnit: external_exports.number().optional(),
|
|
27002
26974
|
/** Optional capability-lineage link to a Beat Version (v2, N-4E09-6574). */
|
|
27003
26975
|
beatVersionId: external_exports.string().optional(),
|
|
26976
|
+
/**
|
|
26977
|
+
* Optional link to the Work Order this item delivers part of (B-331,
|
|
26978
|
+
* N-4E09-7160). Absent means unattached, which is a supported state — a
|
|
26979
|
+
* reader grouping a Track's work by Order must render those as their own
|
|
26980
|
+
* named group, not hide them.
|
|
26981
|
+
*/
|
|
26982
|
+
workOrderId: external_exports.string().min(1).optional(),
|
|
27004
26983
|
createdBy: external_exports.string().optional(),
|
|
27005
26984
|
version: external_exports.number().optional(),
|
|
27006
26985
|
createdAt: external_exports.string(),
|
|
@@ -27137,12 +27116,11 @@ var LayerApiSchema = external_exports.preprocess(
|
|
|
27137
27116
|
const l = raw;
|
|
27138
27117
|
const id = l["systemId"] || l["projectId"];
|
|
27139
27118
|
if (!id) return raw;
|
|
27140
|
-
return { ...l, systemId: id
|
|
27119
|
+
return { ...l, systemId: id };
|
|
27141
27120
|
},
|
|
27142
27121
|
external_exports.object({
|
|
27143
27122
|
layerId: external_exports.string(),
|
|
27144
27123
|
systemId: external_exports.string(),
|
|
27145
|
-
projectId: external_exports.string(),
|
|
27146
27124
|
layerKey: external_exports.string(),
|
|
27147
27125
|
name: external_exports.string(),
|
|
27148
27126
|
description: external_exports.string().nullish(),
|
|
@@ -27199,7 +27177,6 @@ var DeliverableGroupApiSchema = external_exports.preprocess(normalizeSystemId, e
|
|
|
27199
27177
|
groupCode: external_exports.string(),
|
|
27200
27178
|
teamspaceId: external_exports.string(),
|
|
27201
27179
|
systemId: external_exports.string().nullish(),
|
|
27202
|
-
projectId: external_exports.string().nullish(),
|
|
27203
27180
|
movementId: external_exports.string().nullish(),
|
|
27204
27181
|
orgId: external_exports.string(),
|
|
27205
27182
|
title: external_exports.string(),
|
|
@@ -27238,8 +27215,7 @@ var WorkPlanBeatVersionApiSchema = external_exports.preprocess(
|
|
|
27238
27215
|
external_exports.object({
|
|
27239
27216
|
beatVersionId: external_exports.string(),
|
|
27240
27217
|
beatId: external_exports.string(),
|
|
27241
|
-
systemId: external_exports.string()
|
|
27242
|
-
projectId: external_exports.string().optional(),
|
|
27218
|
+
systemId: external_exports.string(),
|
|
27243
27219
|
versionNumber: external_exports.number(),
|
|
27244
27220
|
title: external_exports.string(),
|
|
27245
27221
|
status: BeatVersionStatusSchema,
|
|
@@ -27259,7 +27235,7 @@ var RevisionClaimActorSchema = external_exports.union([
|
|
|
27259
27235
|
external_exports.object({ kind: external_exports.literal("user"), userId: external_exports.string() }),
|
|
27260
27236
|
external_exports.preprocess(
|
|
27261
27237
|
normalizeSystemId,
|
|
27262
|
-
external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string(), systemId: external_exports.string()
|
|
27238
|
+
external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string(), systemId: external_exports.string() })
|
|
27263
27239
|
)
|
|
27264
27240
|
]);
|
|
27265
27241
|
var RevisionClaimSchema = external_exports.object({
|
|
@@ -27279,8 +27255,7 @@ var ProposedRevisionSchema = external_exports.preprocess(
|
|
|
27279
27255
|
state: external_exports.string(),
|
|
27280
27256
|
beatId: external_exports.string(),
|
|
27281
27257
|
beatTitle: external_exports.string().optional(),
|
|
27282
|
-
systemId: external_exports.string()
|
|
27283
|
-
projectId: external_exports.string().optional(),
|
|
27258
|
+
systemId: external_exports.string(),
|
|
27284
27259
|
projectTitle: external_exports.string().optional()
|
|
27285
27260
|
}).passthrough()
|
|
27286
27261
|
);
|
|
@@ -27297,8 +27272,7 @@ var EligibleBeatVersionForDropSchema = external_exports.preprocess(
|
|
|
27297
27272
|
state: external_exports.string(),
|
|
27298
27273
|
beatId: external_exports.string(),
|
|
27299
27274
|
beatTitle: external_exports.string().optional(),
|
|
27300
|
-
systemId: external_exports.string()
|
|
27301
|
-
projectId: external_exports.string().optional(),
|
|
27275
|
+
systemId: external_exports.string(),
|
|
27302
27276
|
projectTitle: external_exports.string().optional(),
|
|
27303
27277
|
createdAt: external_exports.string(),
|
|
27304
27278
|
updatedAt: external_exports.string(),
|
|
@@ -27572,7 +27546,7 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27572
27546
|
return { content: [{ type: "text", text: "orderBy requires beatId \u2014 it is only supported for beat-scoped queries." }], isError: true };
|
|
27573
27547
|
}
|
|
27574
27548
|
try {
|
|
27575
|
-
await
|
|
27549
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27576
27550
|
} catch (err) {
|
|
27577
27551
|
const message = err instanceof Error ? err.message : String(err);
|
|
27578
27552
|
return { content: [{ type: "text", text: `Access denied: ${message}` }], isError: true };
|
|
@@ -27718,7 +27692,7 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27718
27692
|
systemId: external_exports.string().describe("The system ID")
|
|
27719
27693
|
},
|
|
27720
27694
|
async ({ systemId }) => {
|
|
27721
|
-
await
|
|
27695
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27722
27696
|
const DOCUMENT_FETCH_LIMIT = 5e3;
|
|
27723
27697
|
const { notes: docs, hasMore: truncated } = await client.listAllSystemNotes(systemId, { noteType: "document" }, DOCUMENT_FETCH_LIMIT);
|
|
27724
27698
|
const visibleDocs = docs.filter((d) => d.status !== DISMISSED_NOTE_STATUS);
|
|
@@ -27753,7 +27727,7 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27753
27727
|
}
|
|
27754
27728
|
return { content: [{ type: "text", text: formatNoteDetail(note2) }] };
|
|
27755
27729
|
}
|
|
27756
|
-
await
|
|
27730
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27757
27731
|
const note = await client.getNote(noteId);
|
|
27758
27732
|
if (!note) {
|
|
27759
27733
|
return { content: [{ type: "text", text: `Note not found: "${noteId}"` }], isError: true };
|
|
@@ -27792,7 +27766,7 @@ function registerNoteTools(server, ctx, client) {
|
|
|
27792
27766
|
const assumptionMeta = noteType === "assumption" && confidence !== void 0 ? { confidence } : void 0;
|
|
27793
27767
|
let note;
|
|
27794
27768
|
if (systemId) {
|
|
27795
|
-
await
|
|
27769
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27796
27770
|
const projectCode = systemId.substring(0, 4).toUpperCase();
|
|
27797
27771
|
const noteId = await client.getNextNoteId(projectCode, systemId);
|
|
27798
27772
|
note = await client.createNote({
|
|
@@ -27920,7 +27894,7 @@ ${text}` }] };
|
|
|
27920
27894
|
|
|
27921
27895
|
${formatNoteDetail(updated2)}` }] };
|
|
27922
27896
|
}
|
|
27923
|
-
await
|
|
27897
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27924
27898
|
const updated = await client.updateNote(noteId, {
|
|
27925
27899
|
...noteType !== void 0 && { noteType },
|
|
27926
27900
|
status,
|
|
@@ -27962,7 +27936,7 @@ ${text}` }] };
|
|
|
27962
27936
|
},
|
|
27963
27937
|
async ({ systemId, noteIds, noteType, status, content, response, humanAssignee, agentAssignee }) => {
|
|
27964
27938
|
try {
|
|
27965
|
-
await
|
|
27939
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
27966
27940
|
const result = await client.bulkUpdateNotes(noteIds, {
|
|
27967
27941
|
...noteType !== void 0 && { noteType },
|
|
27968
27942
|
status,
|
|
@@ -28001,7 +27975,7 @@ ${text}` }] };
|
|
|
28001
27975
|
},
|
|
28002
27976
|
async ({ systemId, noteId, targetBeatId, targetRevisionId, reason }) => {
|
|
28003
27977
|
try {
|
|
28004
|
-
await
|
|
27978
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
28005
27979
|
const updated = await client.reassignNote(noteId, targetBeatId, reason, ctx.user.userId, targetRevisionId);
|
|
28006
27980
|
if (!updated) {
|
|
28007
27981
|
return { content: [{ type: "text", text: `Note not found: "${noteId}"` }], isError: true };
|
|
@@ -28023,7 +27997,7 @@ ${text}` }] };
|
|
|
28023
27997
|
},
|
|
28024
27998
|
async ({ systemId, noteId, reason }) => {
|
|
28025
27999
|
try {
|
|
28026
|
-
await
|
|
28000
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
28027
28001
|
const note = await client.getNote(noteId);
|
|
28028
28002
|
if (!note || (note.systemId ?? note.projectId) !== systemId) {
|
|
28029
28003
|
return { content: [{ type: "text", text: `Note not found: "${noteId}"` }], isError: true };
|
|
@@ -28050,7 +28024,7 @@ ${text}` }] };
|
|
|
28050
28024
|
},
|
|
28051
28025
|
async ({ systemId, noteId, reason }) => {
|
|
28052
28026
|
try {
|
|
28053
|
-
await
|
|
28027
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
28054
28028
|
const note = await client.getNote(noteId);
|
|
28055
28029
|
if (!note || (note.systemId ?? note.projectId) !== systemId) {
|
|
28056
28030
|
return { content: [{ type: "text", text: `Document not found: "${noteId}"` }], isError: true };
|
|
@@ -28080,7 +28054,7 @@ ${text}` }] };
|
|
|
28080
28054
|
systemId: external_exports.string().describe("The system ID")
|
|
28081
28055
|
},
|
|
28082
28056
|
async ({ systemId }) => {
|
|
28083
|
-
await
|
|
28057
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
28084
28058
|
const assumptions = await client.getKeyAssumptions(systemId);
|
|
28085
28059
|
if (assumptions.length === 0) {
|
|
28086
28060
|
return { content: [{ type: "text", text: "No unvalidated assumptions found." }] };
|
|
@@ -28783,7 +28757,7 @@ function registerOnboardingTools(server, ctx, client) {
|
|
|
28783
28757
|
analysisJson: external_exports.string().optional().describe("JSON-serialized DiscoveryAnalysis from initiate_teamspace_onboarding. Pass this to produce Beats grounded in the actual discovery data.")
|
|
28784
28758
|
},
|
|
28785
28759
|
async ({ systemId, systemTitle, projectDescription, analysisJson }) => {
|
|
28786
|
-
await
|
|
28760
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
28787
28761
|
const result = await client.draftOnboardingBeats(systemId, { systemTitle, projectDescription, analysisJson });
|
|
28788
28762
|
if (!result.suggestions || result.suggestions.length === 0) {
|
|
28789
28763
|
return {
|
|
@@ -29084,7 +29058,7 @@ function registerOrganizationTools(server, ctx, client) {
|
|
|
29084
29058
|
if (system.orgId !== ctx.orgId) {
|
|
29085
29059
|
return { content: [{ type: "text", text: `System "${systemId}" does not belong to the configured organization.` }], isError: true };
|
|
29086
29060
|
}
|
|
29087
|
-
const result = await client.
|
|
29061
|
+
const result = await client.transferSystem(ctx.orgId, systemId, targetOrgId);
|
|
29088
29062
|
if (result.error) {
|
|
29089
29063
|
return { content: [{ type: "text", text: result.error }], isError: true };
|
|
29090
29064
|
}
|
|
@@ -29235,7 +29209,7 @@ function registerPlanQualityTools(server, ctx, client) {
|
|
|
29235
29209
|
isError: true
|
|
29236
29210
|
};
|
|
29237
29211
|
}
|
|
29238
|
-
await
|
|
29212
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
29239
29213
|
const opts = branch || localPath ? { branch, localPath } : void 0;
|
|
29240
29214
|
const task = await client.runCheck(systemId, "beat_version_quality", beatVersionId, opts);
|
|
29241
29215
|
if (!wait) {
|
|
@@ -29382,7 +29356,7 @@ function registerPortfolioCoherenceTools(server, ctx, client) {
|
|
|
29382
29356
|
},
|
|
29383
29357
|
async ({ systemId, wait }) => {
|
|
29384
29358
|
try {
|
|
29385
|
-
await
|
|
29359
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
29386
29360
|
const { taskId } = await client.runCheck(systemId, "portfolio_coherence", systemId);
|
|
29387
29361
|
if (!wait) {
|
|
29388
29362
|
return {
|
|
@@ -29419,7 +29393,7 @@ function registerPortfolioCoherenceTools(server, ctx, client) {
|
|
|
29419
29393
|
const archivedBeatIds = [];
|
|
29420
29394
|
let totalNotesReassigned = 0;
|
|
29421
29395
|
try {
|
|
29422
|
-
await
|
|
29396
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
29423
29397
|
const uniqueBeatIds = [...new Set(beatIds)];
|
|
29424
29398
|
const resolvedPrimaryId = primaryBeatId ?? uniqueBeatIds[0];
|
|
29425
29399
|
if (!uniqueBeatIds.includes(resolvedPrimaryId)) {
|
|
@@ -30172,8 +30146,8 @@ function registerRevisionQualityTools(server, ctx, client) {
|
|
|
30172
30146
|
isError: true
|
|
30173
30147
|
};
|
|
30174
30148
|
}
|
|
30175
|
-
await
|
|
30176
|
-
await
|
|
30149
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
30150
|
+
await assertRevisionInSystem(client, revisionId, systemId);
|
|
30177
30151
|
const task = await client.runCheck(systemId, "revision_quality", revisionId);
|
|
30178
30152
|
if (!wait) {
|
|
30179
30153
|
return {
|
|
@@ -30478,7 +30452,7 @@ function registerSnapshotTools(server, ctx, client) {
|
|
|
30478
30452
|
"Export a complete system snapshot for environment sync. On a remote server (production/staging) returns an S3 presigned URL; on a local server writes to a temp file and returns the path.",
|
|
30479
30453
|
{ systemId: external_exports.string().describe("The system ID to export") },
|
|
30480
30454
|
async ({ systemId }) => {
|
|
30481
|
-
await
|
|
30455
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
30482
30456
|
const result = await client.exportSystemSnapshot(systemId);
|
|
30483
30457
|
if (typeof result === "string") {
|
|
30484
30458
|
if (!result.startsWith("https://")) {
|
|
@@ -30726,7 +30700,7 @@ function registerSubscriptionTools(server, ctx, client) {
|
|
|
30726
30700
|
},
|
|
30727
30701
|
async ({ entityType, entityId, systemId }) => {
|
|
30728
30702
|
try {
|
|
30729
|
-
await
|
|
30703
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
30730
30704
|
await client.subscribe(ctx.user.userId, entityType, entityId, systemId, "manual");
|
|
30731
30705
|
return {
|
|
30732
30706
|
content: [{
|
|
@@ -30790,7 +30764,7 @@ function registerSubscriptionTools(server, ctx, client) {
|
|
|
30790
30764
|
}
|
|
30791
30765
|
|
|
30792
30766
|
// ../../libs/harmonica-services/src/mcp/tools/system-lifecycle-tools.ts
|
|
30793
|
-
function
|
|
30767
|
+
function registerSystemLifecycleTools(server, ctx, client) {
|
|
30794
30768
|
server.tool(
|
|
30795
30769
|
"transition_system_lifecycle",
|
|
30796
30770
|
"Advance a System's capability-maturity lifecycle state. Allowed transitions follow the state machine (Concept \u2192 Incubating \u2192 Piloting \u2192 Activated \u2192 Commercializing \u2192 Scaled, plus paused/killed/sunset/archived exits). The activated \u2192 commercializing edge requires a `decisionNoteId` pointing to a system-scoped Decision Note (the governance review). Other gates are advisory.",
|
|
@@ -30896,7 +30870,7 @@ function registerSystemTools(server, ctx, client) {
|
|
|
30896
30870
|
}) => {
|
|
30897
30871
|
try {
|
|
30898
30872
|
const [project, org] = await Promise.all([
|
|
30899
|
-
|
|
30873
|
+
fetchSystemInOrg(client, systemId, ctx.orgId),
|
|
30900
30874
|
client.getOrg(ctx.orgId)
|
|
30901
30875
|
]);
|
|
30902
30876
|
const notes = await client.listSystemNotes(systemId, {
|
|
@@ -30940,7 +30914,7 @@ function registerSystemTools(server, ctx, client) {
|
|
|
30940
30914
|
if (Object.keys(nonEmpty).length === 0) {
|
|
30941
30915
|
return { content: [{ type: "text", text: "No updates provided." }], isError: true };
|
|
30942
30916
|
}
|
|
30943
|
-
await
|
|
30917
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
30944
30918
|
if (nonEmpty["accountId"] === "") delete nonEmpty["accountId"];
|
|
30945
30919
|
if (typeof updates.teamspaceId === "string") {
|
|
30946
30920
|
const teamspace = await client.getTeamspace(updates.teamspaceId);
|
|
@@ -31279,7 +31253,7 @@ function registerValueVelocityTools(server, ctx, client) {
|
|
|
31279
31253
|
},
|
|
31280
31254
|
async ({ systemId, lens, withLeverage }) => {
|
|
31281
31255
|
try {
|
|
31282
|
-
await
|
|
31256
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
31283
31257
|
const [rankedResult, staleWResult] = await Promise.allSettled([
|
|
31284
31258
|
withLeverage ? client.rankSystemBeatVersionsWithLeverage(systemId, lens) : client.rankSystemBeatVersions(systemId, lens),
|
|
31285
31259
|
client.getStaleWBeatIds(systemId)
|
|
@@ -31386,7 +31360,7 @@ function registerValueVelocityTools(server, ctx, client) {
|
|
|
31386
31360
|
},
|
|
31387
31361
|
async ({ systemId, beatId }) => {
|
|
31388
31362
|
try {
|
|
31389
|
-
await
|
|
31363
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
31390
31364
|
const actorId = resolveActorId(ctx);
|
|
31391
31365
|
if (!actorId) {
|
|
31392
31366
|
return { content: [{ type: "text", text: "Actor identity unavailable: user has no email or userId." }], isError: true };
|
|
@@ -31569,6 +31543,7 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31569
31543
|
wi.valueUnits !== void 0 ? `Value Units: ${wi.valueUnits}` : null,
|
|
31570
31544
|
wi.costPerValueUnit !== void 0 ? `Cost per Value Unit: ${wi.costPerValueUnit}` : null,
|
|
31571
31545
|
wi.beatVersionId ? `Linked Beat Version: ${wi.beatVersionId}` : null,
|
|
31546
|
+
wi.workOrderId ? `Work Order: ${wi.workOrderId}` : "Work Order: none (unattached)",
|
|
31572
31547
|
estimateHint ? `Estimate Hint: ${estimateHint.hours}h (source: ${estimateHint.source})` : null,
|
|
31573
31548
|
wi.createdBy ? `Created By: ${wi.createdBy}` : null,
|
|
31574
31549
|
`Created: ${wi.createdAt}`,
|
|
@@ -31579,7 +31554,7 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31579
31554
|
);
|
|
31580
31555
|
server.tool(
|
|
31581
31556
|
"create_work_item",
|
|
31582
|
-
'Create a work item under a Track (DeliverableGroup). A work item is an owned, statused unit of operational work \u2014 it is NOT a Beat. Starts in "not_started" status. Optionally link it to a Beat Version for capability lineage (v2, N-4E09-6574) \u2014 the link is one-directional and never required.',
|
|
31557
|
+
'Create a work item under a Track (DeliverableGroup). A work item is an owned, statused unit of operational work \u2014 it is NOT a Beat. Starts in "not_started" status. Optionally link it to a Beat Version for capability lineage (v2, N-4E09-6574) \u2014 the link is one-directional and never required. Optionally link it to a Work Order it delivers part of; leaving it unattached is a supported state, not a gap to fill (N-4E09-7160).',
|
|
31583
31558
|
{
|
|
31584
31559
|
trackId: external_exports.string().describe("The Track (DeliverableGroup) ID this work item belongs to"),
|
|
31585
31560
|
title: external_exports.string().min(1).max(300).describe("Work item title"),
|
|
@@ -31590,9 +31565,10 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31590
31565
|
valueUnits: external_exports.number().nonnegative().optional().describe("Optional Value Units (commercial lens) \u2014 independent of effortSize"),
|
|
31591
31566
|
costPerValueUnit: external_exports.number().nonnegative().optional().describe("Optional price per Value Unit"),
|
|
31592
31567
|
createdBy: external_exports.string().optional().describe("Optional creator identity for audit"),
|
|
31593
|
-
beatVersionId: external_exports.string().min(1).optional().describe("Optional Beat Version to link for capability lineage. Must exist.")
|
|
31568
|
+
beatVersionId: external_exports.string().min(1).optional().describe("Optional Beat Version to link for capability lineage. Must exist."),
|
|
31569
|
+
workOrderId: external_exports.string().min(1).max(128).optional().describe("Optional Work Order this item delivers part of. Must exist. Omit when there is no Order \u2014 unattached work is legitimate, so do not invent one.")
|
|
31594
31570
|
},
|
|
31595
|
-
async ({ trackId, title, ownerName, ownerEmail, committedEstimateHours, effortSize, valueUnits, costPerValueUnit, createdBy, beatVersionId }) => {
|
|
31571
|
+
async ({ trackId, title, ownerName, ownerEmail, committedEstimateHours, effortSize, valueUnits, costPerValueUnit, createdBy, beatVersionId, workOrderId }) => {
|
|
31596
31572
|
if (ownerName === void 0 !== (ownerEmail === void 0)) {
|
|
31597
31573
|
return {
|
|
31598
31574
|
content: [{ type: "text", text: "Setting the owner requires both ownerName and ownerEmail. Omit both to create an unowned work item." }],
|
|
@@ -31608,7 +31584,8 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31608
31584
|
...valueUnits !== void 0 && { valueUnits },
|
|
31609
31585
|
...costPerValueUnit !== void 0 && { costPerValueUnit },
|
|
31610
31586
|
...createdBy !== void 0 && { createdBy },
|
|
31611
|
-
...beatVersionId !== void 0 && { beatVersionId }
|
|
31587
|
+
...beatVersionId !== void 0 && { beatVersionId },
|
|
31588
|
+
...workOrderId !== void 0 && { workOrderId }
|
|
31612
31589
|
});
|
|
31613
31590
|
return {
|
|
31614
31591
|
content: [
|
|
@@ -31622,7 +31599,7 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31622
31599
|
);
|
|
31623
31600
|
server.tool(
|
|
31624
31601
|
"update_work_item",
|
|
31625
|
-
"Update mutable content fields on a work item (title, owner, committedEstimateHours, actualHours, effortSize, valueUnits, costPerValueUnit, beatVersionId). To move it between Tracks use move_work_item; to change its status use transition_work_item_status.",
|
|
31602
|
+
"Update mutable content fields on a work item (title, owner, committedEstimateHours, actualHours, effortSize, valueUnits, costPerValueUnit, beatVersionId, workOrderId). To move it between Tracks use move_work_item; to change its status use transition_work_item_status.",
|
|
31626
31603
|
{
|
|
31627
31604
|
workItemId: external_exports.string().describe("The work item ID"),
|
|
31628
31605
|
title: external_exports.string().min(1).max(300).optional().describe("New title"),
|
|
@@ -31634,9 +31611,10 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31634
31611
|
effortSize: external_exports.enum(WORK_ITEM_EFFORT_SIZE_ENUM).nullable().optional().describe("Rough t-shirt effort size (delivery lens). Pass null to clear; omit to leave untouched."),
|
|
31635
31612
|
valueUnits: external_exports.number().nonnegative().nullable().optional().describe("Value Units (commercial lens). Pass null to clear; omit to leave untouched."),
|
|
31636
31613
|
costPerValueUnit: external_exports.number().nonnegative().nullable().optional().describe("Price per Value Unit. Pass null to clear; omit to leave untouched."),
|
|
31637
|
-
beatVersionId: external_exports.string().min(1).nullable().optional().describe("Link to a Beat Version for capability lineage. Pass null to unlink; omit to leave the current link untouched.")
|
|
31614
|
+
beatVersionId: external_exports.string().min(1).nullable().optional().describe("Link to a Beat Version for capability lineage. Pass null to unlink; omit to leave the current link untouched."),
|
|
31615
|
+
workOrderId: external_exports.string().min(1).max(128).nullable().optional().describe("Link to the Work Order this item delivers part of. Pass null to unlink, leaving the item unattached; omit to leave the current link untouched.")
|
|
31638
31616
|
},
|
|
31639
|
-
async ({ workItemId, title, ownerName, ownerEmail, unassignOwner, committedEstimateHours, actualHours, effortSize, valueUnits, costPerValueUnit, beatVersionId }) => {
|
|
31617
|
+
async ({ workItemId, title, ownerName, ownerEmail, unassignOwner, committedEstimateHours, actualHours, effortSize, valueUnits, costPerValueUnit, beatVersionId, workOrderId }) => {
|
|
31640
31618
|
const hasOwnerUpdate = ownerName !== void 0 || ownerEmail !== void 0;
|
|
31641
31619
|
if (hasOwnerUpdate && (ownerName === void 0 || ownerEmail === void 0)) {
|
|
31642
31620
|
return {
|
|
@@ -31650,7 +31628,9 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31650
31628
|
isError: true
|
|
31651
31629
|
};
|
|
31652
31630
|
}
|
|
31653
|
-
const hasUpdates = title !== void 0 || hasOwnerUpdate || unassignOwner === true || committedEstimateHours !== void 0 || actualHours !== void 0 || effortSize !== void 0 || valueUnits !== void 0 || costPerValueUnit !== void 0 || beatVersionId !== void 0
|
|
31631
|
+
const hasUpdates = title !== void 0 || hasOwnerUpdate || unassignOwner === true || committedEstimateHours !== void 0 || actualHours !== void 0 || effortSize !== void 0 || valueUnits !== void 0 || costPerValueUnit !== void 0 || beatVersionId !== void 0 || // `!== undefined`, never truthiness: an unlink arrives as `null`, and
|
|
31632
|
+
// a truthy check here would report "no updates provided" and drop it.
|
|
31633
|
+
workOrderId !== void 0;
|
|
31654
31634
|
if (!hasUpdates) {
|
|
31655
31635
|
return {
|
|
31656
31636
|
content: [{ type: "text", text: `No updates provided for work item: ${workItemId}` }],
|
|
@@ -31666,7 +31646,8 @@ function registerWorkItemTools(server, _ctx, client) {
|
|
|
31666
31646
|
...effortSize !== void 0 && { effortSize },
|
|
31667
31647
|
...valueUnits !== void 0 && { valueUnits },
|
|
31668
31648
|
...costPerValueUnit !== void 0 && { costPerValueUnit },
|
|
31669
|
-
...beatVersionId !== void 0 && { beatVersionId }
|
|
31649
|
+
...beatVersionId !== void 0 && { beatVersionId },
|
|
31650
|
+
...workOrderId !== void 0 && { workOrderId }
|
|
31670
31651
|
});
|
|
31671
31652
|
if (!wi) {
|
|
31672
31653
|
return {
|
|
@@ -32105,7 +32086,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32105
32086
|
limit: external_exports.coerce.number().optional().default(20).describe("Max number of jobs to return")
|
|
32106
32087
|
},
|
|
32107
32088
|
async ({ systemId, status, limit }) => {
|
|
32108
|
-
await
|
|
32089
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32109
32090
|
const tasks = await client.listSystemTasks(systemId, {
|
|
32110
32091
|
status,
|
|
32111
32092
|
limit
|
|
@@ -32163,7 +32144,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32163
32144
|
limit: external_exports.coerce.number().optional().default(20).describe("Max number of jobs to return")
|
|
32164
32145
|
},
|
|
32165
32146
|
async ({ systemId, status, limit }) => {
|
|
32166
|
-
await
|
|
32147
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32167
32148
|
const tasks = await client.listSystemTasks(systemId, {
|
|
32168
32149
|
status,
|
|
32169
32150
|
limit
|
|
@@ -32187,7 +32168,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32187
32168
|
},
|
|
32188
32169
|
async ({ systemId, beatId }) => {
|
|
32189
32170
|
try {
|
|
32190
|
-
await
|
|
32171
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32191
32172
|
const task = await client.draftCoda(systemId, beatId);
|
|
32192
32173
|
return {
|
|
32193
32174
|
content: [{
|
|
@@ -32220,7 +32201,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32220
32201
|
},
|
|
32221
32202
|
async ({ systemId, noteIds }) => {
|
|
32222
32203
|
try {
|
|
32223
|
-
await
|
|
32204
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32224
32205
|
const task = await client.validateAssumptions(systemId, noteIds);
|
|
32225
32206
|
return {
|
|
32226
32207
|
content: [{
|
|
@@ -32255,7 +32236,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32255
32236
|
},
|
|
32256
32237
|
async ({ systemId, message, revisionId }) => {
|
|
32257
32238
|
try {
|
|
32258
|
-
await
|
|
32239
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32259
32240
|
const task = await client.startSession(
|
|
32260
32241
|
systemId,
|
|
32261
32242
|
message,
|
|
@@ -32292,7 +32273,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32292
32273
|
},
|
|
32293
32274
|
async ({ systemId, revisionIds }) => {
|
|
32294
32275
|
try {
|
|
32295
|
-
await
|
|
32276
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32296
32277
|
const task = await client.planRevisionBatch(systemId, revisionIds);
|
|
32297
32278
|
return {
|
|
32298
32279
|
content: [{
|
|
@@ -32324,7 +32305,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32324
32305
|
},
|
|
32325
32306
|
async ({ systemId }) => {
|
|
32326
32307
|
try {
|
|
32327
|
-
await
|
|
32308
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32328
32309
|
const task = await client.runTriage(systemId);
|
|
32329
32310
|
return {
|
|
32330
32311
|
content: [{
|
|
@@ -32370,7 +32351,7 @@ ${JSON.stringify(task.result, null, 2)}
|
|
|
32370
32351
|
},
|
|
32371
32352
|
async ({ systemId, content, filename, encoding }) => {
|
|
32372
32353
|
try {
|
|
32373
|
-
await
|
|
32354
|
+
await assertSystemInOrg(client, systemId, ctx.orgId);
|
|
32374
32355
|
const result = encoding === "base64" ? await client.analyzeBinaryDocument(systemId, content, filename) : await client.analyzeDocument(systemId, content, filename);
|
|
32375
32356
|
return {
|
|
32376
32357
|
content: [{
|
|
@@ -32447,7 +32428,7 @@ var TOOL_PROFILES = Object.freeze({
|
|
|
32447
32428
|
registerTeamspaceTools,
|
|
32448
32429
|
registerMembershipTools,
|
|
32449
32430
|
registerSystemTools,
|
|
32450
|
-
|
|
32431
|
+
registerSystemLifecycleTools,
|
|
32451
32432
|
allow(registerBeatVersionTools, ["relocate_beat_version"])
|
|
32452
32433
|
]),
|
|
32453
32434
|
"onboarding": Object.freeze([
|
|
@@ -32485,7 +32466,7 @@ function registerAllTools(server, ctx, client, profile) {
|
|
|
32485
32466
|
return;
|
|
32486
32467
|
}
|
|
32487
32468
|
registerSystemTools(server, ctx, client);
|
|
32488
|
-
|
|
32469
|
+
registerSystemLifecycleTools(server, ctx, client);
|
|
32489
32470
|
registerMembershipTools(server, ctx, client);
|
|
32490
32471
|
registerBeatTools(server, ctx, client);
|
|
32491
32472
|
registerBeatConvergenceTools(server, ctx, client);
|
|
@@ -32808,7 +32789,7 @@ function createHttpClient(config2) {
|
|
|
32808
32789
|
return { error: String(err) };
|
|
32809
32790
|
}
|
|
32810
32791
|
},
|
|
32811
|
-
|
|
32792
|
+
transferSystem: async (sourceOrgId, projectId, targetOrgId) => {
|
|
32812
32793
|
try {
|
|
32813
32794
|
const result = await request(
|
|
32814
32795
|
"POST",
|
|
@@ -33936,7 +33917,7 @@ function createHttpClient(config2) {
|
|
|
33936
33917
|
return importResult;
|
|
33937
33918
|
},
|
|
33938
33919
|
// Embedding similarity
|
|
33939
|
-
|
|
33920
|
+
embedSystemEntities: (projectId) => request("POST", `/api/systems/${encodeURIComponent(projectId)}/embeddings/generate`),
|
|
33940
33921
|
findSimilarNotes: async (noteId, projectId, options) => {
|
|
33941
33922
|
const qs = buildSimilarityQS(options);
|
|
33942
33923
|
const res = await request("GET", `/api/systems/${encodeURIComponent(projectId)}/notes/${encodeURIComponent(noteId)}/similar${qs}`);
|
|
@@ -34180,7 +34161,7 @@ function createHttpClient(config2) {
|
|
|
34180
34161
|
},
|
|
34181
34162
|
// WorkItems (WorkItem exposure layer — owned, statused unit of operational work under a Track)
|
|
34182
34163
|
createWorkItem: async (input) => {
|
|
34183
|
-
const { trackId, title, owner, committedEstimateHours, effortSize, valueUnits, costPerValueUnit, createdBy, beatVersionId } = input;
|
|
34164
|
+
const { trackId, title, owner, committedEstimateHours, effortSize, valueUnits, costPerValueUnit, createdBy, beatVersionId, workOrderId } = input;
|
|
34184
34165
|
const body = {
|
|
34185
34166
|
title,
|
|
34186
34167
|
...owner !== void 0 && { owner },
|
|
@@ -34189,7 +34170,8 @@ function createHttpClient(config2) {
|
|
|
34189
34170
|
...valueUnits !== void 0 && { valueUnits },
|
|
34190
34171
|
...costPerValueUnit !== void 0 && { costPerValueUnit },
|
|
34191
34172
|
...createdBy !== void 0 && { createdBy },
|
|
34192
|
-
...beatVersionId !== void 0 && { beatVersionId }
|
|
34173
|
+
...beatVersionId !== void 0 && { beatVersionId },
|
|
34174
|
+
...workOrderId !== void 0 && { workOrderId }
|
|
34193
34175
|
};
|
|
34194
34176
|
const res = await request(
|
|
34195
34177
|
"POST",
|
|
@@ -34930,7 +34912,7 @@ function loadConfig() {
|
|
|
34930
34912
|
};
|
|
34931
34913
|
}
|
|
34932
34914
|
async function main() {
|
|
34933
|
-
console.error(`[harmonica-mcp] v${"3.9.
|
|
34915
|
+
console.error(`[harmonica-mcp] v${"3.9.1"} starting\u2026`);
|
|
34934
34916
|
const config2 = loadConfig();
|
|
34935
34917
|
const client = createHttpClient({
|
|
34936
34918
|
apiBaseUrl: config2.apiBaseUrl,
|