mcp-ai-agent-guidelines
Version:
A comprehensive Model Context Protocol server providing advanced tools, resources, and prompts for implementing AI agent best practices
299 lines • 13.2 kB
JavaScript
import { polyglotGateway } from "../../../gateway/polyglot-gateway.js";
import { OutputApproach } from "../../../strategies/output-strategy.js";
import { sessionNotFoundError, validationError, } from "../../shared/error-factory.js";
import { adrGenerator } from "../adr-generator.js";
import { constraintManager } from "../constraint-manager.js";
import { crossSessionConsistencyEnforcer } from "../cross-session-consistency-enforcer.js";
import { designPhaseWorkflow } from "../design-phase-workflow.js";
import { roadmapGenerator } from "../roadmap-generator.js";
import { specGenerator } from "../spec-generator.js";
class ArtifactGenerationServiceImpl {
async generateArtifacts(sessionId, artifactTypes) {
const sessionState = designPhaseWorkflow.getSession(sessionId);
if (!sessionState) {
throw sessionNotFoundError(sessionId);
}
const artifacts = [];
const recommendations = [];
// Generate requested artifacts
try {
if (artifactTypes.includes("adr")) {
const sessionADRs = await adrGenerator.generateSessionADRs(sessionState);
const adrsArray = Array.isArray(sessionADRs) ? sessionADRs : [];
artifacts.push(...adrsArray);
recommendations.push(`Generated ${adrsArray.length} ADR(s)`);
}
if (artifactTypes.includes("specification")) {
const specResult = await specGenerator.generateSpecification({
sessionState,
title: `${sessionState.config.goal} Technical Specification`,
type: "technical",
});
artifacts.push(specResult.artifact);
const specRecs = Array.isArray(specResult.recommendations)
? specResult.recommendations.slice(0, 2)
: [];
recommendations.push(...specRecs);
}
if (artifactTypes.includes("roadmap")) {
const roadmapResult = await roadmapGenerator.generateRoadmap({
sessionState,
title: `${sessionState.config.goal} Implementation Roadmap`,
});
artifacts.push(roadmapResult.artifact);
const roadmapRecs = Array.isArray(roadmapResult.recommendations)
? roadmapResult.recommendations.slice(0, 2)
: [];
recommendations.push(...roadmapRecs);
}
if (artifactTypes.includes("speckit")) {
const speckitArtifacts = await this.generateSpecKitArtifacts(sessionState);
artifacts.push(...speckitArtifacts);
recommendations.push(`Generated ${speckitArtifacts.length} Spec-Kit artifact(s)`);
}
// Update session artifacts
sessionState.artifacts.push(...artifacts);
return {
success: true,
sessionId,
currentPhase: sessionState.currentPhase,
status: "artifacts-generated",
message: `Generated ${artifacts.length} artifact(s) successfully`,
recommendations: [...new Set(recommendations)],
artifacts,
};
}
catch (error) {
throw validationError("Artifact generation failed", {
sessionId,
artifactsGenerated: artifacts.length,
reason: error instanceof Error ? error.message : String(error),
});
}
}
async generateConstraintDocumentation(sessionId) {
// Get current session state and generate consistency report
const mockSessionState = {
config: {
sessionId,
context: "Constraint documentation generation",
goal: "Generate automated documentation for constraint decisions",
requirements: [],
constraints: constraintManager.getConstraints(),
coverageThreshold: 85,
enablePivots: false,
templateRefs: [],
outputFormats: ["markdown"],
metadata: {},
},
currentPhase: "requirements",
phases: {},
artifacts: [],
coverage: {
overall: 0,
phases: {},
constraints: {},
assumptions: {},
documentation: {},
testCoverage: 0,
},
history: [],
status: "active",
};
try {
const consistencyReport = await crossSessionConsistencyEnforcer.enforceConsistency(mockSessionState);
const documentation = await crossSessionConsistencyEnforcer.generateConstraintDocumentation(mockSessionState, consistencyReport);
const artifacts = [
{
id: `adr-${sessionId}-${Date.now()}`,
name: "Cross-Session Constraint Consistency ADR",
type: "adr",
content: documentation.adr,
format: "markdown",
metadata: { generated: new Date().toISOString() },
timestamp: new Date().toISOString(),
},
{
id: `spec-${sessionId}-${Date.now()}`,
name: "Cross-Session Constraint Specification",
type: "specification",
content: documentation.specification,
format: "markdown",
metadata: { generated: new Date().toISOString() },
timestamp: new Date().toISOString(),
},
{
id: `roadmap-${sessionId}-${Date.now()}`,
name: "Cross-Session Consistency Roadmap",
type: "roadmap",
content: documentation.roadmap,
format: "markdown",
metadata: { generated: new Date().toISOString() },
timestamp: new Date().toISOString(),
},
];
return {
success: true,
sessionId,
status: "documentation-generated",
message: `Generated ${artifacts.length} constraint documentation artifacts`,
recommendations: [
"Review generated ADR for constraint decisions",
"Use specification for implementation guidance",
"Follow roadmap for consistency improvements",
],
artifacts,
data: {
consistencyReport,
documentation,
},
};
}
catch (error) {
throw validationError("Constraint documentation generation failed", {
sessionId,
reason: error instanceof Error ? error.message : String(error),
});
}
}
/**
* Generate Spec-Kit artifacts from a design session state.
*
* Converts the session state to SessionState format and uses PolyglotGateway
* with SpecKitStrategy to generate spec.md, plan.md, tasks.md, and progress.md.
*
* @param sessionState - The design session state
* @returns Array of Spec-Kit artifacts
* @private
*/
async generateSpecKitArtifacts(sessionState) {
// Convert DesignSessionState to SessionState for PolyglotGateway
const domainResult = this.convertSessionToDomainResult(sessionState);
// Use PolyglotGateway to render Spec-Kit artifacts
const gatewayArtifacts = polyglotGateway.render({
domainResult,
domainType: "SessionState",
approach: OutputApproach.SPECKIT,
});
// Convert gateway output documents to Artifact format
const artifacts = [];
const timestamp = new Date().toISOString();
const baseId = `speckit-${sessionState.config.sessionId}-${Date.now()}`;
// Add primary artifact (README.md)
artifacts.push({
id: `${baseId}-primary`,
name: gatewayArtifacts.primary.name,
type: "speckit",
content: gatewayArtifacts.primary.content,
format: this.mapGatewayFormatToOutputFormat(gatewayArtifacts.primary.format),
timestamp,
metadata: { source: "polyglot-gateway", artifactType: "primary" },
});
// Add secondary artifacts (spec.md, plan.md, tasks.md, progress.md, etc.)
if (gatewayArtifacts.secondary?.length) {
for (const [idx, secondary] of gatewayArtifacts.secondary.entries()) {
artifacts.push({
id: `${baseId}-secondary-${idx}`,
name: secondary.name,
type: "speckit",
content: secondary.content,
format: this.mapGatewayFormatToOutputFormat(secondary.format),
timestamp,
metadata: { source: "polyglot-gateway", artifactType: "secondary" },
});
}
}
return artifacts;
}
/**
* Convert DesignSessionState to SessionState for PolyglotGateway.
*
* Maps the design assistant's session state format to the domain's SessionState
* format expected by the SpecKitStrategy.
*
* @param session - The design session state
* @returns SessionState for gateway rendering
* @private
*/
convertSessionToDomainResult(session) {
// Build phase history from session events
const phaseTransitions = session.history
.filter((event) => event.type === "phase-start" || event.type === "phase-complete")
.map((event, idx, events) => {
// For phase transitions, extract from/to from consecutive events or event data
const fromPhase = idx > 0 ? events[idx - 1].phase || "unknown" : "unknown";
const toPhase = event.phase || "unknown";
return {
from: fromPhase,
to: toPhase,
timestamp: event.timestamp,
type: event.type,
description: event.description,
};
});
return {
id: session.config.sessionId,
phase: session.currentPhase || "discovery",
currentPhase: session.currentPhase,
config: {
sessionId: session.config.sessionId,
context: {
overview: session.config.context,
goal: session.config.goal,
},
goal: session.config.goal,
requirements: session.config.requirements,
constraints: session.config.constraints,
metadata: session.config.metadata,
},
context: {
overview: session.config.context,
objectives: session.config.requirements.map((r) => ({
description: r,
})),
requirements: session.config.requirements.map((r) => ({
description: r,
type: "functional",
})),
acceptanceCriteria: [],
outOfScope: [],
},
phases: session.phases,
coverage: session.coverage,
artifacts: session.artifacts.reduce((acc, artifact, idx) => {
acc[artifact.name || `artifact-${idx}`] = artifact;
return acc;
}, {}),
status: session.status,
history: phaseTransitions,
};
}
/**
* Map gateway OutputDocument format to design assistant OutputFormat.
*
* The gateway supports an additional "shell" format that is not part of the
* design assistant's OutputFormat union. Rather than implicitly coercing
* "shell" to "markdown" (which can be semantically misleading), this method
* treats "shell" as an unsupported format and raises a validation error.
*
* Callers should ensure that the gateway is requested to produce one of the
* supported formats ("markdown", "yaml", or "json") for design artifacts.
*
* @param format - Gateway output format
* @returns Design assistant OutputFormat
* @throws ValidationError if an unsupported format (e.g., "shell") is provided
* @private
*/
mapGatewayFormatToOutputFormat(format) {
// Explicitly reject "shell" rather than silently mapping it to "markdown"
if (format === "shell") {
throw validationError('Gateway output format "shell" is not supported for design assistant artifacts. Please request "markdown", "yaml", or "json" instead.', { format });
}
return format;
}
}
// Export singleton instance
export const artifactGenerationService = new ArtifactGenerationServiceImpl();
// Module Implementation Status Sentinel
export const IMPLEMENTATION_STATUS = "IMPLEMENTED";
//# sourceMappingURL=artifact-generation.service.js.map