86 lines
2.6 KiB
JavaScript
86 lines
2.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Factory Router — V2 Protocol Stack → Full-stack Factory Bridge
|
|
*
|
|
* Routes a structured PRD to the appropriate factory chain.
|
|
* No factory logic lives here — only routing decisions.
|
|
*
|
|
* Current factories:
|
|
* - fullstack → SF-01 (project-intake) + SF-02 (architecture) + SF-03~06 (fullstack-composer)
|
|
*
|
|
* Future factories (routing placeholder):
|
|
* - research → 科研工厂
|
|
* - writing → 写作工厂
|
|
* - analysis → 分析工厂
|
|
*
|
|
* @module factory-router
|
|
*/
|
|
|
|
/**
|
|
* Route a PRD to the appropriate factory.
|
|
* Currently only "fullstack" is implemented.
|
|
*
|
|
* @param {object} prd — Structured PRD from SF-01
|
|
* @param {object} opts
|
|
* @param {object} opts.arch — Architecture from SF-02 (optional, auto-generated if missing)
|
|
* @param {string} opts.factory — Force a factory ("fullstack" | "research" | "writing" | "analysis")
|
|
* @returns {{ factory: string, factoryFn: string, needsArch: boolean }}
|
|
*/
|
|
export function route(prd, opts = {}) {
|
|
const domain = prd.domain || "generic";
|
|
|
|
// Resolve factory name
|
|
let factory = opts.factory || _inferFactory(domain, prd);
|
|
|
|
// All factories need architecture → default to fullstack pipeline for now
|
|
if (factory === "fullstack") {
|
|
return {
|
|
factory: "fullstack",
|
|
factoryFn: "./fullstack-composer-agent.mjs",
|
|
needsArch: !opts.arch,
|
|
};
|
|
}
|
|
|
|
// Unknown or future factory → default to fullstack
|
|
return {
|
|
factory: "fullstack",
|
|
factoryFn: "./fullstack-composer-agent.mjs",
|
|
needsArch: !opts.arch,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Infer factory type from domain and PRD content.
|
|
*
|
|
* @param {string} domain
|
|
* @param {object} prd
|
|
* @returns {string} factory name
|
|
*/
|
|
function _inferFactory(domain, prd) {
|
|
// Research domains → research factory (future)
|
|
const researchDomains = ["research", "academic", "scientific", "paper", "thesis"];
|
|
if (researchDomains.includes(domain)) return "research";
|
|
|
|
// Writing domains → writing factory (future)
|
|
const writingDomains = ["writing", "blog", "article", "news"];
|
|
if (writingDomains.includes(domain)) return "writing";
|
|
|
|
// Analysis domains → analysis factory (future)
|
|
const analysisDomains = ["analytics", "dashboard", "report"];
|
|
if (analysisDomains.includes(domain)) return "analysis";
|
|
|
|
// Default: fullstack factory
|
|
return "fullstack";
|
|
}
|
|
|
|
/**
|
|
* Load a factory module. Keeps dynamic import lazy.
|
|
*
|
|
* @param {string} factoryFn — Path to factory script (relative to scripts/)
|
|
* @returns {Promise<object>} factory module
|
|
*/
|
|
export async function loadFactory(factoryFn) {
|
|
return await import(factoryFn);
|
|
}
|