You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function modelPath(root, name) { return path.join(projectPaths(root).model, `${name}.json`); }
28
+
function tracePath(root, page) { return path.join(projectPaths(root).traceability, 'pages', `${page.id}.json`); }
29
+
function validateJson(file) { const value = readJson(file); if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`Invalid JSON object: ${file}`); return value; }
return `${base}\n\nRecovery request: write only the requested model object(s). For a single requested name, a direct object or a named wrapper is accepted. Do not repeat unrelated models.`;
95
+
};
96
+
async function requestBundle(expected, target, repair = false) {
97
+
temporaryArtifacts.add(target); const before = artifactStamp(target); let extraction = null;
98
+
const inspect = () => {
99
+
if (!artifactChanged(target, before)) return null;
await synthesizeBundle(root, 'modelCore', ['system', 'business', 'flows', 'catalogs'], 'repository structure architecture components modules symbols interfaces contracts dependencies behavior domain rules states flows data and automation; detect technologies from evidence and do not assume a language or framework');
55
+
ingestModels(root);
56
+
await synthesizeBundle(root, 'modelEnterprise', ['security', 'operations', 'testing', 'data-governance', 'decisions', 'configuration', 'change-impact', 'ownership'], 'security operations testing governance configuration ownership decisions change impact reliability consistency and compatibility across any language framework runtime or deployment model');
57
+
return ingestModels(root);
58
+
}
59
+
60
+
function canonicalPagePath(page, category, id) {
61
+
let value = String(page.path ?? '').replaceAll('\\', '/').replace(/^\/+/, '');
62
+
if (!value) value = `docs/${category}/${slug(page.slug ?? page.title ?? id)}.md`;
63
+
if (!value.startsWith('docs/')) value = `docs/${value}`;
const paths = projectPaths(root); const manifest = readJson(paths.plan); if (!Array.isArray(manifest.pages) || !manifest.pages.length) throw new Error('Manifest must contain non-empty pages[].');
73
+
manifest.pages = manifest.pages.map(normalizePage); const ids = new Set(); const files = new Set(); const max = Number(loadConfig(root).execution?.maxPlannedPages ?? 30);
74
+
if (max > 0 && manifest.pages.length > max) throw new Error(`Manifest contains ${manifest.pages.length} pages, above execution.maxPlannedPages=${max}. Consolidate duplicate user intents or raise the limit explicitly.`);
75
+
for (const page of manifest.pages) {
76
+
if (ids.has(page.id)) throw new Error(`Duplicate page id: ${page.id}`); if (files.has(page.path)) throw new Error(`Duplicate page path: ${page.path}`);
77
+
if (!page.title.trim() || !page.summary.trim()) throw new Error(`Page ${page.id} requires non-empty title and summary.`);
0 commit comments