@cubis/foundry 0.3.79 → 0.3.81
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/cli/build/commands.js +1 -1
- package/dist/cli/build/commands.js.map +1 -1
- package/dist/cli/core.js +324 -149
- package/dist/cli/core.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/build/commands.ts +1 -1
- package/src/cli/core.ts +368 -194
- package/workflows/workflows/agent-environment-setup/generated/route-manifest.json +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/accessibility.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/architecture.toml +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/backend.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/create.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/database.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/debug.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/devops.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/implement-track.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/migrate.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/mobile.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/onboard.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/orchestrate.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/plan.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/refactor.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/release.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/review.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/security.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/spec.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/test.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/vercel.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/platforms/antigravity/workflows/spec.md +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/claude/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/platforms/claude/workflows/spec.md +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/codex/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/platforms/codex/workflows/spec.md +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-accessibility.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-architecture.prompt.md +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-backend.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-create.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-database.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-debug.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-devops.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-implement-track.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-migrate.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-mobile.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-onboard.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-orchestrate.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-plan.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-refactor.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-release.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-review.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-security.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-spec.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-test.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-vercel.prompt.md +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/copilot/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/platforms/copilot/workflows/spec.md +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/accessibility.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/architecture.toml +2 -2
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/backend.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/create.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/database.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/debug.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/devops.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/implement-track.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/migrate.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/mobile.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/onboard.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/orchestrate.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/plan.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/refactor.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/release.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/review.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/security.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/spec.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/test.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/vercel.toml +1 -1
- package/workflows/workflows/agent-environment-setup/platforms/gemini/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/platforms/gemini/workflows/spec.md +2 -2
- package/workflows/workflows/agent-environment-setup/shared/workflows/architecture.md +22 -19
- package/workflows/workflows/agent-environment-setup/shared/workflows/spec.md +2 -2
package/src/cli/core.ts
CHANGED
|
@@ -81,6 +81,8 @@ const ROADMAP_FOUNDATION_BLOCK_START_RE =
|
|
|
81
81
|
/<!--\s*cbx:roadmap:foundation:start[^>]*-->/g;
|
|
82
82
|
const ROADMAP_FOUNDATION_BLOCK_END_RE =
|
|
83
83
|
/<!--\s*cbx:roadmap:foundation:end\s*-->/g;
|
|
84
|
+
const FOUNDATION_DOCS_DIR = path.join("docs", "foundation");
|
|
85
|
+
const FOUNDATION_ADR_DIR = path.join(FOUNDATION_DOCS_DIR, "adr");
|
|
84
86
|
const COPILOT_ALLOWED_SKILL_FRONTMATTER_KEYS = new Set([
|
|
85
87
|
"compatibility",
|
|
86
88
|
"description",
|
|
@@ -1312,7 +1314,7 @@ function buildEngineeringArchitectureSection(snapshot) {
|
|
|
1312
1314
|
...profile.testingStrategy.map((rule) => ` - ${rule}`),
|
|
1313
1315
|
"- Doc refresh policy:",
|
|
1314
1316
|
" - Update these managed sections when architecture, scale, boundaries, design-system rules, or testing strategy changes.",
|
|
1315
|
-
|
|
1317
|
+
` - For non-trivial work, read ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ENGINEERING_RULES.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, and ${FOUNDATION_DOCS_DIR}/TECH.md in that order when they exist.`,
|
|
1316
1318
|
"<!-- cbx:architecture:rules:end -->",
|
|
1317
1319
|
"",
|
|
1318
1320
|
].join("\n");
|
|
@@ -1436,7 +1438,7 @@ function buildRoadmapFoundationSection(snapshot, specRoots = []) {
|
|
|
1436
1438
|
"- Use this section for medium-term scaling themes, major migrations, or cross-team architecture investments.",
|
|
1437
1439
|
"",
|
|
1438
1440
|
"### Backbone Maintenance",
|
|
1439
|
-
|
|
1441
|
+
`- Keep ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ENGINEERING_RULES.md, and ${FOUNDATION_DOCS_DIR}/TECH.md aligned when direction or structure changes.`,
|
|
1440
1442
|
"- Link major roadmap themes back to specs and ADRs instead of burying them in chat-only planning.",
|
|
1441
1443
|
"<!-- cbx:roadmap:foundation:end -->",
|
|
1442
1444
|
"",
|
|
@@ -1578,6 +1580,45 @@ function buildRoadmapTemplate(snapshot, specRoots = []) {
|
|
|
1578
1580
|
].join("\n");
|
|
1579
1581
|
}
|
|
1580
1582
|
|
|
1583
|
+
function buildProductBuildSkeleton() {
|
|
1584
|
+
return [
|
|
1585
|
+
"# Product",
|
|
1586
|
+
"",
|
|
1587
|
+
"This file is managed by `cbx build architecture`.",
|
|
1588
|
+
"",
|
|
1589
|
+
"<!-- cbx:product:foundation:start version=1 profile=uninitialized -->",
|
|
1590
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
1591
|
+
"<!-- cbx:product:foundation:end -->",
|
|
1592
|
+
"",
|
|
1593
|
+
].join("\n");
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
function buildArchitectureBuildSkeleton() {
|
|
1597
|
+
return [
|
|
1598
|
+
"# Architecture",
|
|
1599
|
+
"",
|
|
1600
|
+
"This file is managed by `cbx build architecture`.",
|
|
1601
|
+
"",
|
|
1602
|
+
"<!-- cbx:architecture:doc:start version=1 profile=uninitialized -->",
|
|
1603
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
1604
|
+
"<!-- cbx:architecture:doc:end -->",
|
|
1605
|
+
"",
|
|
1606
|
+
].join("\n");
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
function buildTechBuildSkeleton() {
|
|
1610
|
+
return [
|
|
1611
|
+
"# TECH.md",
|
|
1612
|
+
"",
|
|
1613
|
+
"This file is managed by `cbx build architecture`.",
|
|
1614
|
+
"",
|
|
1615
|
+
"<!-- cbx:architecture:tech:start version=1 snapshot=uninitialized -->",
|
|
1616
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
1617
|
+
"<!-- cbx:architecture:tech:end -->",
|
|
1618
|
+
"",
|
|
1619
|
+
].join("\n");
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1581
1622
|
function buildAdrReadme() {
|
|
1582
1623
|
return [
|
|
1583
1624
|
"# Architecture Decision Records",
|
|
@@ -1663,7 +1704,7 @@ function buildEngineeringRulesManagedBlock({
|
|
|
1663
1704
|
"2. Keep architecture simple (KISS) and avoid speculative work (YAGNI).",
|
|
1664
1705
|
"3. Apply SOLID pragmatically to reduce change risk, not add ceremony.",
|
|
1665
1706
|
"4. Use clear naming with focused responsibilities and explicit boundaries.",
|
|
1666
|
-
|
|
1707
|
+
`5. For non-trivial work, read ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ENGINEERING_RULES.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, and ${FOUNDATION_DOCS_DIR}/TECH.md in that order when they exist before planning or implementation.`,
|
|
1667
1708
|
"6. Require validation evidence (lint/types/tests) before merge.",
|
|
1668
1709
|
"7. Use Decision Log response style.",
|
|
1669
1710
|
"8. Every Decision Log must include a `Skills Used` section listing skill, workflow, or agent names.",
|
|
@@ -1888,6 +1929,17 @@ async function upsertTaggedSectionInFile({
|
|
|
1888
1929
|
trimmed.length > 0 ? `${trimmed}\n\n${block}\n` : `${block}\n`;
|
|
1889
1930
|
}
|
|
1890
1931
|
|
|
1932
|
+
if (!exists) {
|
|
1933
|
+
if (!dryRun) {
|
|
1934
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
1935
|
+
await writeFile(targetPath, nextContent, "utf8");
|
|
1936
|
+
}
|
|
1937
|
+
return {
|
|
1938
|
+
action: dryRun ? "would-create" : "created",
|
|
1939
|
+
filePath: targetPath,
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1891
1943
|
if (nextContent === original) {
|
|
1892
1944
|
return {
|
|
1893
1945
|
action: "unchanged",
|
|
@@ -1915,23 +1967,15 @@ async function upsertTaggedSectionInFile({
|
|
|
1915
1967
|
function buildArchitectureBuildMetadata({
|
|
1916
1968
|
platform,
|
|
1917
1969
|
researchMode,
|
|
1918
|
-
|
|
1919
|
-
architectureDocHash,
|
|
1920
|
-
rulesProfileHash,
|
|
1921
|
-
techSnapshotHash,
|
|
1922
|
-
roadmapProfileHash,
|
|
1970
|
+
managedDocs,
|
|
1923
1971
|
}) {
|
|
1924
1972
|
return {
|
|
1925
|
-
schemaVersion:
|
|
1973
|
+
schemaVersion: 3,
|
|
1926
1974
|
generatedBy: "cbx build architecture",
|
|
1927
1975
|
generatedAt: new Date().toISOString(),
|
|
1928
1976
|
platform,
|
|
1929
1977
|
researchMode,
|
|
1930
|
-
|
|
1931
|
-
architectureDocHash,
|
|
1932
|
-
rulesProfileHash,
|
|
1933
|
-
techSnapshotHash,
|
|
1934
|
-
roadmapProfileHash,
|
|
1978
|
+
managedDocs,
|
|
1935
1979
|
};
|
|
1936
1980
|
}
|
|
1937
1981
|
|
|
@@ -2043,6 +2087,87 @@ async function ensureArchitectureDocScaffold({
|
|
|
2043
2087
|
};
|
|
2044
2088
|
}
|
|
2045
2089
|
|
|
2090
|
+
async function ensureArchitectureBuildScaffold({
|
|
2091
|
+
workspaceRoot,
|
|
2092
|
+
dryRun = false,
|
|
2093
|
+
}) {
|
|
2094
|
+
const foundationRoot = path.join(workspaceRoot, FOUNDATION_DOCS_DIR);
|
|
2095
|
+
const productPath = path.join(foundationRoot, "PRODUCT.md");
|
|
2096
|
+
const architectureDocPath = path.join(foundationRoot, "ARCHITECTURE.md");
|
|
2097
|
+
const techMdPath = path.join(foundationRoot, "TECH.md");
|
|
2098
|
+
const adrDir = path.join(workspaceRoot, FOUNDATION_ADR_DIR);
|
|
2099
|
+
const adrReadmePath = path.join(adrDir, "README.md");
|
|
2100
|
+
const adrTemplatePath = path.join(adrDir, "0000-template.md");
|
|
2101
|
+
|
|
2102
|
+
const productResult = await upsertTaggedSectionInFile({
|
|
2103
|
+
targetPath: productPath,
|
|
2104
|
+
initialContent: `${buildProductBuildSkeleton()}\n`,
|
|
2105
|
+
block: [
|
|
2106
|
+
"<!-- cbx:product:foundation:start version=1 profile=uninitialized -->",
|
|
2107
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
2108
|
+
"<!-- cbx:product:foundation:end -->",
|
|
2109
|
+
"",
|
|
2110
|
+
].join("\n"),
|
|
2111
|
+
startPattern: PRODUCT_FOUNDATION_BLOCK_START_RE,
|
|
2112
|
+
endPattern: PRODUCT_FOUNDATION_BLOCK_END_RE,
|
|
2113
|
+
dryRun,
|
|
2114
|
+
});
|
|
2115
|
+
|
|
2116
|
+
const architectureDocResult = await upsertTaggedSectionInFile({
|
|
2117
|
+
targetPath: architectureDocPath,
|
|
2118
|
+
initialContent: `${buildArchitectureBuildSkeleton()}\n`,
|
|
2119
|
+
block: [
|
|
2120
|
+
"<!-- cbx:architecture:doc:start version=1 profile=uninitialized -->",
|
|
2121
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
2122
|
+
"<!-- cbx:architecture:doc:end -->",
|
|
2123
|
+
"",
|
|
2124
|
+
].join("\n"),
|
|
2125
|
+
startPattern: ARCHITECTURE_DOC_BLOCK_START_RE,
|
|
2126
|
+
endPattern: ARCHITECTURE_DOC_BLOCK_END_RE,
|
|
2127
|
+
dryRun,
|
|
2128
|
+
});
|
|
2129
|
+
|
|
2130
|
+
const techResult = await upsertTaggedSectionInFile({
|
|
2131
|
+
targetPath: techMdPath,
|
|
2132
|
+
initialContent: `${buildTechBuildSkeleton()}\n`,
|
|
2133
|
+
block: [
|
|
2134
|
+
"<!-- cbx:architecture:tech:start version=1 snapshot=uninitialized -->",
|
|
2135
|
+
"Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
|
|
2136
|
+
"<!-- cbx:architecture:tech:end -->",
|
|
2137
|
+
"",
|
|
2138
|
+
].join("\n"),
|
|
2139
|
+
startPattern: TECH_ARCHITECTURE_BLOCK_START_RE,
|
|
2140
|
+
endPattern: TECH_ARCHITECTURE_BLOCK_END_RE,
|
|
2141
|
+
dryRun,
|
|
2142
|
+
});
|
|
2143
|
+
|
|
2144
|
+
const adrReadmeResult = await writeTextFile({
|
|
2145
|
+
targetPath: adrReadmePath,
|
|
2146
|
+
content: `${buildAdrReadme()}\n`,
|
|
2147
|
+
overwrite: false,
|
|
2148
|
+
dryRun,
|
|
2149
|
+
});
|
|
2150
|
+
const adrTemplateResult = await writeTextFile({
|
|
2151
|
+
targetPath: adrTemplatePath,
|
|
2152
|
+
content: `${buildAdrTemplate()}\n`,
|
|
2153
|
+
overwrite: false,
|
|
2154
|
+
dryRun,
|
|
2155
|
+
});
|
|
2156
|
+
|
|
2157
|
+
return {
|
|
2158
|
+
productPath,
|
|
2159
|
+
architectureDocPath,
|
|
2160
|
+
techMdPath,
|
|
2161
|
+
adrReadmePath,
|
|
2162
|
+
adrTemplatePath,
|
|
2163
|
+
productResult,
|
|
2164
|
+
architectureDocResult,
|
|
2165
|
+
techResult,
|
|
2166
|
+
adrReadmeResult,
|
|
2167
|
+
adrTemplateResult,
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2046
2171
|
function normalizeTechPackageName(value) {
|
|
2047
2172
|
if (value === undefined || value === null) return null;
|
|
2048
2173
|
const normalized = String(value)
|
|
@@ -12711,7 +12836,7 @@ function printInstallDocumentationNotice() {
|
|
|
12711
12836
|
"- Install only wires the rule references and workflow assets.",
|
|
12712
12837
|
);
|
|
12713
12838
|
console.log(
|
|
12714
|
-
|
|
12839
|
+
`- Use \`cbx rules init\` to scaffold ENGINEERING_RULES.md and TECH.md, or \`cbx build architecture --platform <codex|claude|gemini|copilot>\` to generate ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ${FOUNDATION_DOCS_DIR}/TECH.md, and ADR scaffolds.`,
|
|
12715
12840
|
);
|
|
12716
12841
|
}
|
|
12717
12842
|
|
|
@@ -12896,6 +13021,68 @@ async function listSpecPackRoots(workspaceRoot) {
|
|
|
12896
13021
|
.slice(0, 8);
|
|
12897
13022
|
}
|
|
12898
13023
|
|
|
13024
|
+
async function resolveArchitectureInspectionAnchors(
|
|
13025
|
+
workspaceRoot,
|
|
13026
|
+
snapshot,
|
|
13027
|
+
specRoots,
|
|
13028
|
+
) {
|
|
13029
|
+
const seen = new Set();
|
|
13030
|
+
const ordered = [];
|
|
13031
|
+
const pushCandidate = async (relativePath) => {
|
|
13032
|
+
const normalized = toPosixPath(relativePath);
|
|
13033
|
+
if (!normalized || seen.has(normalized)) return;
|
|
13034
|
+
if (!(await pathExists(path.join(workspaceRoot, relativePath)))) return;
|
|
13035
|
+
seen.add(normalized);
|
|
13036
|
+
ordered.push(normalized);
|
|
13037
|
+
};
|
|
13038
|
+
|
|
13039
|
+
for (const candidate of [
|
|
13040
|
+
"README.md",
|
|
13041
|
+
"package.json",
|
|
13042
|
+
"pubspec.yaml",
|
|
13043
|
+
"go.mod",
|
|
13044
|
+
"pyproject.toml",
|
|
13045
|
+
"Cargo.toml",
|
|
13046
|
+
"Dockerfile",
|
|
13047
|
+
"docker-compose.yml",
|
|
13048
|
+
"docker-compose.yaml",
|
|
13049
|
+
"compose.yaml",
|
|
13050
|
+
"cbx_config.json",
|
|
13051
|
+
".vscode/mcp.json",
|
|
13052
|
+
".gemini/settings.json",
|
|
13053
|
+
]) {
|
|
13054
|
+
await pushCandidate(candidate);
|
|
13055
|
+
}
|
|
13056
|
+
|
|
13057
|
+
for (const specRoot of specRoots.slice(0, 4)) {
|
|
13058
|
+
await pushCandidate(specRoot);
|
|
13059
|
+
}
|
|
13060
|
+
|
|
13061
|
+
for (const app of snapshot.architectureByApp || []) {
|
|
13062
|
+
if (!app?.rootPath || app.rootPath === ".") continue;
|
|
13063
|
+
await pushCandidate(app.rootPath);
|
|
13064
|
+
for (const child of [
|
|
13065
|
+
"README.md",
|
|
13066
|
+
"src",
|
|
13067
|
+
"lib",
|
|
13068
|
+
"app",
|
|
13069
|
+
"prisma",
|
|
13070
|
+
"migrations",
|
|
13071
|
+
"test",
|
|
13072
|
+
"tests",
|
|
13073
|
+
"docs",
|
|
13074
|
+
]) {
|
|
13075
|
+
await pushCandidate(path.join(app.rootPath, child));
|
|
13076
|
+
}
|
|
13077
|
+
}
|
|
13078
|
+
|
|
13079
|
+
for (const dir of snapshot.topDirs || []) {
|
|
13080
|
+
await pushCandidate(dir);
|
|
13081
|
+
}
|
|
13082
|
+
|
|
13083
|
+
return ordered.slice(0, 18);
|
|
13084
|
+
}
|
|
13085
|
+
|
|
12899
13086
|
function resolveArchitectureConditionalSkills(snapshot, specRoots, researchMode) {
|
|
12900
13087
|
const conditional = [];
|
|
12901
13088
|
const frameworks = new Set(snapshot.frameworks || []);
|
|
@@ -12958,17 +13145,17 @@ function buildArchitecturePrompt({
|
|
|
12958
13145
|
workspaceRoot,
|
|
12959
13146
|
snapshot,
|
|
12960
13147
|
specRoots,
|
|
13148
|
+
inspectionAnchors,
|
|
12961
13149
|
researchMode,
|
|
12962
13150
|
coreSkills,
|
|
12963
13151
|
conditionalSkills,
|
|
12964
13152
|
skillPathHints,
|
|
12965
13153
|
}) {
|
|
12966
|
-
const productPath =
|
|
12967
|
-
const architecturePath =
|
|
12968
|
-
const
|
|
12969
|
-
const
|
|
12970
|
-
const
|
|
12971
|
-
const adrReadmePath = "docs/adr/README.md";
|
|
13154
|
+
const productPath = `${FOUNDATION_DOCS_DIR}/PRODUCT.md`;
|
|
13155
|
+
const architecturePath = `${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md`;
|
|
13156
|
+
const techPath = `${FOUNDATION_DOCS_DIR}/TECH.md`;
|
|
13157
|
+
const adrReadmePath = `${FOUNDATION_ADR_DIR}/README.md`;
|
|
13158
|
+
const adrTemplatePath = `${FOUNDATION_ADR_DIR}/0000-template.md`;
|
|
12972
13159
|
const architectureSignals = snapshot.architectureByApp
|
|
12973
13160
|
.filter((item) => (item.architectureSignals || []).length > 0)
|
|
12974
13161
|
.map((item) => {
|
|
@@ -12980,8 +13167,8 @@ function buildArchitecturePrompt({
|
|
|
12980
13167
|
`You are running inside ${platform}.`,
|
|
12981
13168
|
"",
|
|
12982
13169
|
"Objective:",
|
|
12983
|
-
`- Inspect the repository at ${toPosixPath(workspaceRoot)} and refresh the
|
|
12984
|
-
"-
|
|
13170
|
+
`- Inspect the repository at ${toPosixPath(workspaceRoot)} and author or refresh the core foundation docs in ${productPath}, ${architecturePath}, ${techPath}, ${adrReadmePath}, and ${adrTemplatePath}.`,
|
|
13171
|
+
"- The content should be primarily AI-authored from repository inspection, not copied from placeholder scaffolding.",
|
|
12985
13172
|
"- Preserve manual content outside the managed `cbx:*` markers.",
|
|
12986
13173
|
"",
|
|
12987
13174
|
"Required skill bundle:",
|
|
@@ -13001,27 +13188,38 @@ function buildArchitecturePrompt({
|
|
|
13001
13188
|
architectureSignals.length > 0
|
|
13002
13189
|
? `- Architecture signals: ${architectureSignals.join(" | ")}`
|
|
13003
13190
|
: "- Architecture signals: none confidently inferred from the repo scan",
|
|
13191
|
+
`- Entry points: ${snapshot.entryPoints.length > 0 ? snapshot.entryPoints.slice(0, 8).join(" | ") : "none detected"}`,
|
|
13192
|
+
`- Key scripts: ${snapshot.keyScripts.length > 0 ? snapshot.keyScripts.slice(0, 8).map((item) => `${item.name}=${item.command}`).join(" | ") : "none detected"}`,
|
|
13193
|
+
`- Inspection anchors: ${inspectionAnchors.length > 0 ? inspectionAnchors.join(", ") : "no concrete anchors detected; inspect the repo root, main source trees, and manifest files manually"}`,
|
|
13004
13194
|
"",
|
|
13005
13195
|
"Execution contract:",
|
|
13006
|
-
|
|
13007
|
-
"2.
|
|
13008
|
-
"3.
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13196
|
+
"1. Inspect the repository first before writing any backbone doc content. Derive structure, product surfaces, runtime boundaries, and technical constraints from the actual codebase.",
|
|
13197
|
+
"2. Complete a real inspection pass before drafting. At minimum, inspect the concrete anchors listed above, plus any adjacent directories needed to understand the main execution paths, data boundaries, and integration surfaces.",
|
|
13198
|
+
"3. Do not infer architecture from filenames alone when you can open representative files. Read enough source to validate the main app boundaries, runtime flows, and persistence/integration patterns.",
|
|
13199
|
+
`4. Then read ${productPath}, ${architecturePath}, and ${techPath} in that order when they exist so you can preserve useful manual context and update existing managed sections cleanly.`,
|
|
13200
|
+
`5. Replace or update only the content between the existing managed markers in ${productPath}, ${architecturePath}, and ${techPath}. Do not append a second marker block.`,
|
|
13201
|
+
`6. In ${productPath}, write a concrete product foundation: product purpose, primary users/operators, main journeys, business capabilities, operational constraints, and what future contributors must preserve.`,
|
|
13202
|
+
`7. In ${architecturePath}, write a lean but detailed architecture backbone in a pragmatic arc42/C4 style: system purpose and constraints, explicit architecture classification, bounded contexts, major building blocks, dependency rules, data and integration boundaries, runtime flows, deployment/operability notes, testing/debugging strategy, and only the diagram levels that add real value.`,
|
|
13203
|
+
`8. ${architecturePath} must include a dedicated folder-structure guide that lists the important apps/packages/directories, what each owns, and how contributors should treat those boundaries when editing code.`,
|
|
13204
|
+
`9. In ${techPath}, write the developer-facing technical map: stack, repo layout, key commands, entrypoints, data stores, external services, environment/config surfaces, MCP/tooling footprint, and change hotspots future agents should inspect before editing code.`,
|
|
13205
|
+
`10. ${techPath} should complement ${architecturePath}; do not repeat the same structure prose unless it helps a developer act faster.`,
|
|
13206
|
+
`11. Use exact required headings in ${productPath}: \`## Product Scope\`, \`## Product Purpose\`, \`## Primary Users And Operators\`, \`## Main Journeys\`, \`## Business Capabilities That Matter\`, \`## Operational Constraints\`, \`## Preservation Rules For Future Contributors\`.`,
|
|
13207
|
+
`12. Use exact required headings in ${architecturePath}: \`## Architecture Type\`, \`## System Purpose\`, \`## Constraints And Architectural Drivers\`, \`## Repository Structure Guide\`, \`## Bounded Contexts\`, \`## Major Building Blocks\`, \`## Dependency Rules\`, \`## Data Boundaries\`, \`## Integration Boundaries\`, \`## Runtime Flows\`, \`## Deployment And Operability\`, \`## Testing And Debugging Strategy\`, \`## Architectural Guidance\`.`,
|
|
13208
|
+
`13. Use exact required headings in ${techPath}: \`## Stack Snapshot\`, \`## Repository Layout\`, \`## Entrypoints\`, \`## Key Commands\`, \`## Runtime Data Stores\`, \`## External Services And Integration Surfaces\`, \`## Environment And Config Surfaces\`, \`## Generated Artifacts To Respect\`, \`## Change Hotspots\`, \`## Practical Editing Notes\`.`,
|
|
13209
|
+
"14. Every major claim should be grounded in repository evidence. Mention concrete repo paths in the docs when a structural claim would otherwise be ambiguous.",
|
|
13210
|
+
"15. Avoid placeholder filler, generic checklists, and duplicated content across files. Each doc should have a clear job.",
|
|
13211
|
+
"16. Do not create ROADMAP.md, ENGINEERING_RULES.md, or other extra docs unless the prompt explicitly asks for them.",
|
|
13014
13212
|
researchMode === "never"
|
|
13015
|
-
? "
|
|
13016
|
-
: "
|
|
13213
|
+
? "17. Stay repo-only. Do not use outside research."
|
|
13214
|
+
: "17. Use repo evidence first. Use official docs when needed. Treat Reddit or community sources only as labeled secondary evidence.",
|
|
13017
13215
|
researchMode === "always"
|
|
13018
|
-
?
|
|
13019
|
-
: "
|
|
13020
|
-
|
|
13021
|
-
`
|
|
13216
|
+
? `18. Include an external research evidence subsection in ${techPath} with clearly labeled primary and secondary evidence.`
|
|
13217
|
+
: "18. Include external research notes only if they materially informed the architecture update.",
|
|
13218
|
+
`19. If the project clearly follows Clean Architecture, feature-first modules, DDD, modular monolith, or another stable structure, make that explicit in ${architecturePath} with evidence from the repo.`,
|
|
13219
|
+
`20. Ensure ${adrReadmePath} and ${adrTemplatePath} exist as ADR entrypoints, but keep them lean.`,
|
|
13022
13220
|
"",
|
|
13023
13221
|
"Return one JSON object on the last line with this shape:",
|
|
13024
|
-
|
|
13222
|
+
`{"files_written":["${productPath}","${architecturePath}","${techPath}","${adrReadmePath}","${adrTemplatePath}"],"research_used":false,"gaps":[],"next_actions":[]}`,
|
|
13025
13223
|
"",
|
|
13026
13224
|
"Do not emit placeholder TODOs in the managed sections.",
|
|
13027
13225
|
].join("\n");
|
|
@@ -13283,14 +13481,94 @@ async function captureFileContents(filePaths) {
|
|
|
13283
13481
|
return snapshot;
|
|
13284
13482
|
}
|
|
13285
13483
|
|
|
13484
|
+
function collectTaggedBlocks(content, startPattern, endPattern) {
|
|
13485
|
+
const blocks = [];
|
|
13486
|
+
let cursor = 0;
|
|
13487
|
+
const startMatcher = new RegExp(
|
|
13488
|
+
startPattern.source,
|
|
13489
|
+
startPattern.flags.replace(/g/g, ""),
|
|
13490
|
+
);
|
|
13491
|
+
const endMatcher = new RegExp(
|
|
13492
|
+
endPattern.source,
|
|
13493
|
+
endPattern.flags.replace(/g/g, ""),
|
|
13494
|
+
);
|
|
13495
|
+
while (cursor < content.length) {
|
|
13496
|
+
const remaining = content.slice(cursor);
|
|
13497
|
+
const startMatch = remaining.match(startMatcher);
|
|
13498
|
+
if (!startMatch || startMatch.index == null) break;
|
|
13499
|
+
const startIndex = cursor + startMatch.index;
|
|
13500
|
+
const afterStart = content.slice(startIndex + startMatch[0].length);
|
|
13501
|
+
const endMatch = afterStart.match(endMatcher);
|
|
13502
|
+
if (!endMatch || endMatch.index == null) break;
|
|
13503
|
+
const endIndex =
|
|
13504
|
+
startIndex + startMatch[0].length + endMatch.index + endMatch[0].length;
|
|
13505
|
+
const block = content.slice(startIndex, endIndex);
|
|
13506
|
+
const inner = content
|
|
13507
|
+
.slice(startIndex + startMatch[0].length, endIndex - endMatch[0].length)
|
|
13508
|
+
.trim();
|
|
13509
|
+
blocks.push({
|
|
13510
|
+
startIndex,
|
|
13511
|
+
endIndex,
|
|
13512
|
+
block,
|
|
13513
|
+
score: inner.length,
|
|
13514
|
+
});
|
|
13515
|
+
cursor = endIndex;
|
|
13516
|
+
}
|
|
13517
|
+
return blocks;
|
|
13518
|
+
}
|
|
13519
|
+
|
|
13520
|
+
async function collapseDuplicateTaggedBlocks({
|
|
13521
|
+
targetPath,
|
|
13522
|
+
startPattern,
|
|
13523
|
+
endPattern,
|
|
13524
|
+
}) {
|
|
13525
|
+
if (!(await pathExists(targetPath))) return { changed: false };
|
|
13526
|
+
|
|
13527
|
+
const content = await readFile(targetPath, "utf8");
|
|
13528
|
+
const blocks = collectTaggedBlocks(content, startPattern, endPattern);
|
|
13529
|
+
if (blocks.length <= 1) return { changed: false };
|
|
13530
|
+
|
|
13531
|
+
const bestBlock = [...blocks].sort((a, b) => b.score - a.score)[0];
|
|
13532
|
+
const first = blocks[0];
|
|
13533
|
+
const last = blocks[blocks.length - 1];
|
|
13534
|
+
const normalized =
|
|
13535
|
+
content.slice(0, first.startIndex) +
|
|
13536
|
+
bestBlock.block +
|
|
13537
|
+
content.slice(last.endIndex);
|
|
13538
|
+
|
|
13539
|
+
if (normalized === content) return { changed: false };
|
|
13540
|
+
|
|
13541
|
+
await writeFile(targetPath, normalized, "utf8");
|
|
13542
|
+
return { changed: true };
|
|
13543
|
+
}
|
|
13544
|
+
|
|
13545
|
+
async function normalizeArchitectureBuildOutputs(scaffold) {
|
|
13546
|
+
await collapseDuplicateTaggedBlocks({
|
|
13547
|
+
targetPath: scaffold.productPath,
|
|
13548
|
+
startPattern: PRODUCT_FOUNDATION_BLOCK_START_RE,
|
|
13549
|
+
endPattern: PRODUCT_FOUNDATION_BLOCK_END_RE,
|
|
13550
|
+
});
|
|
13551
|
+
await collapseDuplicateTaggedBlocks({
|
|
13552
|
+
targetPath: scaffold.architectureDocPath,
|
|
13553
|
+
startPattern: ARCHITECTURE_DOC_BLOCK_START_RE,
|
|
13554
|
+
endPattern: ARCHITECTURE_DOC_BLOCK_END_RE,
|
|
13555
|
+
});
|
|
13556
|
+
await collapseDuplicateTaggedBlocks({
|
|
13557
|
+
targetPath: scaffold.techMdPath,
|
|
13558
|
+
startPattern: TECH_ARCHITECTURE_BLOCK_START_RE,
|
|
13559
|
+
endPattern: TECH_ARCHITECTURE_BLOCK_END_RE,
|
|
13560
|
+
});
|
|
13561
|
+
}
|
|
13562
|
+
|
|
13286
13563
|
async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
13287
|
-
const
|
|
13288
|
-
const
|
|
13289
|
-
|
|
13290
|
-
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
const
|
|
13564
|
+
const productPath = path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md");
|
|
13565
|
+
const architecturePath = path.join(
|
|
13566
|
+
workspaceRoot,
|
|
13567
|
+
FOUNDATION_DOCS_DIR,
|
|
13568
|
+
"ARCHITECTURE.md",
|
|
13569
|
+
);
|
|
13570
|
+
const techPath = path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md");
|
|
13571
|
+
const adrReadmePath = path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md");
|
|
13294
13572
|
const metadataPath = path.join(
|
|
13295
13573
|
workspaceRoot,
|
|
13296
13574
|
".cbx",
|
|
@@ -13298,41 +13576,16 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
|
13298
13576
|
);
|
|
13299
13577
|
const productExists = await pathExists(productPath);
|
|
13300
13578
|
const architectureExists = await pathExists(architecturePath);
|
|
13301
|
-
const rulesExists = await pathExists(rulesPath);
|
|
13302
13579
|
const techExists = await pathExists(techPath);
|
|
13303
|
-
const roadmapExists = await pathExists(roadmapPath);
|
|
13304
13580
|
const adrReadmeExists = await pathExists(adrReadmePath);
|
|
13305
13581
|
|
|
13306
|
-
const expectedProductHash = hashStableObject(
|
|
13307
|
-
inferProductFoundationProfile(snapshot, specRoots),
|
|
13308
|
-
);
|
|
13309
|
-
const expectedArchitectureHash = hashStableObject(
|
|
13310
|
-
inferArchitectureDocProfile(snapshot, specRoots),
|
|
13311
|
-
);
|
|
13312
|
-
const expectedRulesHash = hashStableObject(
|
|
13313
|
-
inferArchitectureContractProfile(snapshot),
|
|
13314
|
-
);
|
|
13315
|
-
const expectedTechHash = hashStableObject({
|
|
13316
|
-
style: inferArchitectureContractProfile(snapshot).style,
|
|
13317
|
-
topDirs: snapshot.topDirs,
|
|
13318
|
-
frameworks: snapshot.frameworks,
|
|
13319
|
-
architectureByApp: snapshot.architectureByApp,
|
|
13320
|
-
});
|
|
13321
|
-
const expectedRoadmapHash = hashStableObject({
|
|
13322
|
-
topDirs: snapshot.topDirs,
|
|
13323
|
-
frameworks: snapshot.frameworks,
|
|
13324
|
-
specRoots,
|
|
13325
|
-
});
|
|
13326
|
-
|
|
13327
13582
|
const findings = [];
|
|
13328
13583
|
let actualProductHash = null;
|
|
13329
13584
|
let actualArchitectureHash = null;
|
|
13330
|
-
let actualRulesHash = null;
|
|
13331
13585
|
let actualTechHash = null;
|
|
13332
|
-
let actualRoadmapHash = null;
|
|
13333
13586
|
|
|
13334
13587
|
if (!productExists) {
|
|
13335
|
-
findings.push(
|
|
13588
|
+
findings.push(`${FOUNDATION_DOCS_DIR}/PRODUCT.md is missing.`);
|
|
13336
13589
|
} else {
|
|
13337
13590
|
const content = await readFile(productPath, "utf8");
|
|
13338
13591
|
actualProductHash = extractTaggedMarkerAttribute(
|
|
@@ -13341,16 +13594,14 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
|
13341
13594
|
"profile",
|
|
13342
13595
|
);
|
|
13343
13596
|
if (!actualProductHash) {
|
|
13344
|
-
findings.push("PRODUCT.md is missing the managed product foundation block.");
|
|
13345
|
-
} else if (actualProductHash !== expectedProductHash) {
|
|
13346
13597
|
findings.push(
|
|
13347
|
-
|
|
13598
|
+
`${FOUNDATION_DOCS_DIR}/PRODUCT.md is missing the managed product foundation block.`,
|
|
13348
13599
|
);
|
|
13349
13600
|
}
|
|
13350
13601
|
}
|
|
13351
13602
|
|
|
13352
13603
|
if (!architectureExists) {
|
|
13353
|
-
findings.push(
|
|
13604
|
+
findings.push(`${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md is missing.`);
|
|
13354
13605
|
} else {
|
|
13355
13606
|
const content = await readFile(architecturePath, "utf8");
|
|
13356
13607
|
actualArchitectureHash = extractTaggedMarkerAttribute(
|
|
@@ -13359,34 +13610,14 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
|
13359
13610
|
"profile",
|
|
13360
13611
|
);
|
|
13361
13612
|
if (!actualArchitectureHash) {
|
|
13362
|
-
findings.push("ARCHITECTURE.md is missing the managed architecture backbone block.");
|
|
13363
|
-
} else if (actualArchitectureHash !== expectedArchitectureHash) {
|
|
13364
|
-
findings.push(
|
|
13365
|
-
`ARCHITECTURE.md backbone is stale (expected ${expectedArchitectureHash}, found ${actualArchitectureHash}).`,
|
|
13366
|
-
);
|
|
13367
|
-
}
|
|
13368
|
-
}
|
|
13369
|
-
|
|
13370
|
-
if (!rulesExists) {
|
|
13371
|
-
findings.push("ENGINEERING_RULES.md is missing.");
|
|
13372
|
-
} else {
|
|
13373
|
-
const content = await readFile(rulesPath, "utf8");
|
|
13374
|
-
actualRulesHash = extractTaggedMarkerAttribute(
|
|
13375
|
-
content,
|
|
13376
|
-
ENGINEERING_ARCHITECTURE_BLOCK_START_RE,
|
|
13377
|
-
"profile",
|
|
13378
|
-
);
|
|
13379
|
-
if (!actualRulesHash) {
|
|
13380
|
-
findings.push("ENGINEERING_RULES.md is missing the managed architecture contract block.");
|
|
13381
|
-
} else if (actualRulesHash !== expectedRulesHash) {
|
|
13382
13613
|
findings.push(
|
|
13383
|
-
|
|
13614
|
+
`${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md is missing the managed architecture backbone block.`,
|
|
13384
13615
|
);
|
|
13385
13616
|
}
|
|
13386
13617
|
}
|
|
13387
13618
|
|
|
13388
13619
|
if (!techExists) {
|
|
13389
|
-
findings.push(
|
|
13620
|
+
findings.push(`${FOUNDATION_DOCS_DIR}/TECH.md is missing.`);
|
|
13390
13621
|
} else {
|
|
13391
13622
|
const content = await readFile(techPath, "utf8");
|
|
13392
13623
|
actualTechHash = extractTaggedMarkerAttribute(
|
|
@@ -13395,34 +13626,14 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
|
13395
13626
|
"snapshot",
|
|
13396
13627
|
);
|
|
13397
13628
|
if (!actualTechHash) {
|
|
13398
|
-
findings.push("TECH.md is missing the managed architecture snapshot block.");
|
|
13399
|
-
} else if (actualTechHash !== expectedTechHash) {
|
|
13400
13629
|
findings.push(
|
|
13401
|
-
|
|
13402
|
-
);
|
|
13403
|
-
}
|
|
13404
|
-
}
|
|
13405
|
-
|
|
13406
|
-
if (!roadmapExists) {
|
|
13407
|
-
findings.push("ROADMAP.md is missing.");
|
|
13408
|
-
} else {
|
|
13409
|
-
const content = await readFile(roadmapPath, "utf8");
|
|
13410
|
-
actualRoadmapHash = extractTaggedMarkerAttribute(
|
|
13411
|
-
content,
|
|
13412
|
-
ROADMAP_FOUNDATION_BLOCK_START_RE,
|
|
13413
|
-
"profile",
|
|
13414
|
-
);
|
|
13415
|
-
if (!actualRoadmapHash) {
|
|
13416
|
-
findings.push("ROADMAP.md is missing the managed roadmap foundation block.");
|
|
13417
|
-
} else if (actualRoadmapHash !== expectedRoadmapHash) {
|
|
13418
|
-
findings.push(
|
|
13419
|
-
`ROADMAP.md backbone is stale (expected ${expectedRoadmapHash}, found ${actualRoadmapHash}).`,
|
|
13630
|
+
`${FOUNDATION_DOCS_DIR}/TECH.md is missing the managed architecture snapshot block.`,
|
|
13420
13631
|
);
|
|
13421
13632
|
}
|
|
13422
13633
|
}
|
|
13423
13634
|
|
|
13424
13635
|
if (!adrReadmeExists) {
|
|
13425
|
-
findings.push(
|
|
13636
|
+
findings.push(`${FOUNDATION_ADR_DIR}/README.md is missing.`);
|
|
13426
13637
|
}
|
|
13427
13638
|
|
|
13428
13639
|
const metadata = await readJsonFileIfExists(metadataPath);
|
|
@@ -13435,21 +13646,12 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
|
|
|
13435
13646
|
findings,
|
|
13436
13647
|
productPath,
|
|
13437
13648
|
architecturePath,
|
|
13438
|
-
rulesPath,
|
|
13439
13649
|
techPath,
|
|
13440
|
-
roadmapPath,
|
|
13441
13650
|
adrReadmePath,
|
|
13442
13651
|
metadataPath,
|
|
13443
|
-
expectedProductHash,
|
|
13444
|
-
expectedArchitectureHash,
|
|
13445
|
-
expectedRulesHash,
|
|
13446
|
-
expectedTechHash,
|
|
13447
|
-
expectedRoadmapHash,
|
|
13448
13652
|
actualProductHash,
|
|
13449
13653
|
actualArchitectureHash,
|
|
13450
|
-
actualRulesHash,
|
|
13451
13654
|
actualTechHash,
|
|
13452
|
-
actualRoadmapHash,
|
|
13453
13655
|
};
|
|
13454
13656
|
}
|
|
13455
13657
|
|
|
@@ -13475,7 +13677,7 @@ async function runBuildArchitecture(options) {
|
|
|
13475
13677
|
console.log(`Workspace: ${toPosixPath(workspaceRoot)}`);
|
|
13476
13678
|
console.log(`Status: ${drift.stale ? "stale" : "fresh"}`);
|
|
13477
13679
|
console.log(
|
|
13478
|
-
|
|
13680
|
+
`Backbone docs: ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ${FOUNDATION_DOCS_DIR}/TECH.md, ${FOUNDATION_ADR_DIR}/README.md`,
|
|
13479
13681
|
);
|
|
13480
13682
|
if (drift.findings.length > 0) {
|
|
13481
13683
|
console.log("Findings:");
|
|
@@ -13489,25 +13691,12 @@ async function runBuildArchitecture(options) {
|
|
|
13489
13691
|
}
|
|
13490
13692
|
|
|
13491
13693
|
const managedFilePaths = [
|
|
13492
|
-
path.join(workspaceRoot, "PRODUCT.md"),
|
|
13493
|
-
path.join(workspaceRoot, "ARCHITECTURE.md"),
|
|
13494
|
-
path.join(workspaceRoot, "
|
|
13495
|
-
path.join(workspaceRoot, "
|
|
13496
|
-
path.join(workspaceRoot, "
|
|
13497
|
-
path.join(workspaceRoot, "docs", "adr", "README.md"),
|
|
13498
|
-
path.join(workspaceRoot, "docs", "adr", "0000-template.md"),
|
|
13694
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md"),
|
|
13695
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "ARCHITECTURE.md"),
|
|
13696
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md"),
|
|
13697
|
+
path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md"),
|
|
13698
|
+
path.join(workspaceRoot, FOUNDATION_ADR_DIR, "0000-template.md"),
|
|
13499
13699
|
];
|
|
13500
|
-
const filesBefore = dryRun
|
|
13501
|
-
? Object.fromEntries(managedFilePaths.map((filePath) => [filePath, null]))
|
|
13502
|
-
: await captureFileContents(managedFilePaths);
|
|
13503
|
-
|
|
13504
|
-
const scaffold = await ensureArchitectureDocScaffold({
|
|
13505
|
-
workspaceRoot,
|
|
13506
|
-
snapshot,
|
|
13507
|
-
specRoots,
|
|
13508
|
-
overwrite,
|
|
13509
|
-
dryRun,
|
|
13510
|
-
});
|
|
13511
13700
|
const coreSkills = [
|
|
13512
13701
|
"architecture-doc",
|
|
13513
13702
|
"system-design",
|
|
@@ -13525,11 +13714,17 @@ async function runBuildArchitecture(options) {
|
|
|
13525
13714
|
cwd,
|
|
13526
13715
|
skillBundle,
|
|
13527
13716
|
);
|
|
13717
|
+
const inspectionAnchors = await resolveArchitectureInspectionAnchors(
|
|
13718
|
+
workspaceRoot,
|
|
13719
|
+
snapshot,
|
|
13720
|
+
specRoots,
|
|
13721
|
+
);
|
|
13528
13722
|
const prompt = buildArchitecturePrompt({
|
|
13529
13723
|
platform,
|
|
13530
13724
|
workspaceRoot,
|
|
13531
13725
|
snapshot,
|
|
13532
13726
|
specRoots,
|
|
13727
|
+
inspectionAnchors,
|
|
13533
13728
|
researchMode,
|
|
13534
13729
|
coreSkills,
|
|
13535
13730
|
conditionalSkills,
|
|
@@ -13537,6 +13732,13 @@ async function runBuildArchitecture(options) {
|
|
|
13537
13732
|
});
|
|
13538
13733
|
const adapter = await probeArchitectureAdapter(platform, workspaceRoot);
|
|
13539
13734
|
const args = adapter.buildInvocation(prompt);
|
|
13735
|
+
const managedTargets = [
|
|
13736
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md"),
|
|
13737
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "ARCHITECTURE.md"),
|
|
13738
|
+
path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md"),
|
|
13739
|
+
path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md"),
|
|
13740
|
+
path.join(workspaceRoot, FOUNDATION_ADR_DIR, "0000-template.md"),
|
|
13741
|
+
].map((filePath) => toPosixPath(filePath));
|
|
13540
13742
|
|
|
13541
13743
|
if (dryRun) {
|
|
13542
13744
|
const summary = {
|
|
@@ -13545,15 +13747,7 @@ async function runBuildArchitecture(options) {
|
|
|
13545
13747
|
adapter: adapter.binary,
|
|
13546
13748
|
invocation: [adapter.binary, ...args],
|
|
13547
13749
|
researchMode,
|
|
13548
|
-
managedTargets
|
|
13549
|
-
toPosixPath(scaffold.productPath),
|
|
13550
|
-
toPosixPath(scaffold.architectureDocPath),
|
|
13551
|
-
toPosixPath(scaffold.engineeringRulesPath),
|
|
13552
|
-
toPosixPath(scaffold.techMdPath),
|
|
13553
|
-
toPosixPath(scaffold.roadmapPath),
|
|
13554
|
-
toPosixPath(scaffold.adrReadmePath),
|
|
13555
|
-
toPosixPath(scaffold.adrTemplatePath),
|
|
13556
|
-
],
|
|
13750
|
+
managedTargets,
|
|
13557
13751
|
skillBundle,
|
|
13558
13752
|
};
|
|
13559
13753
|
if (emitJson) {
|
|
@@ -13564,7 +13758,7 @@ async function runBuildArchitecture(options) {
|
|
|
13564
13758
|
console.log(`Adapter: ${adapter.binary}`);
|
|
13565
13759
|
console.log(`Research mode: ${researchMode}`);
|
|
13566
13760
|
console.log(
|
|
13567
|
-
`Managed targets: ${
|
|
13761
|
+
`Managed targets: ${summary.managedTargets.join(", ")}`,
|
|
13568
13762
|
);
|
|
13569
13763
|
console.log(`Skill bundle: ${skillBundle.join(", ")}`);
|
|
13570
13764
|
console.log(`Invocation: ${[adapter.binary, ...args].join(" ")}`);
|
|
@@ -13572,6 +13766,12 @@ async function runBuildArchitecture(options) {
|
|
|
13572
13766
|
return;
|
|
13573
13767
|
}
|
|
13574
13768
|
|
|
13769
|
+
const filesBefore = await captureFileContents(managedFilePaths);
|
|
13770
|
+
const scaffold = await ensureArchitectureBuildScaffold({
|
|
13771
|
+
workspaceRoot,
|
|
13772
|
+
dryRun,
|
|
13773
|
+
});
|
|
13774
|
+
|
|
13575
13775
|
if (!emitJson) {
|
|
13576
13776
|
console.log(`Streaming ${adapter.binary} output...`);
|
|
13577
13777
|
}
|
|
@@ -13585,14 +13785,13 @@ async function runBuildArchitecture(options) {
|
|
|
13585
13785
|
throw new Error(explainArchitectureBuildFailure(platform, execution));
|
|
13586
13786
|
}
|
|
13587
13787
|
|
|
13788
|
+
await normalizeArchitectureBuildOutputs(scaffold);
|
|
13789
|
+
|
|
13588
13790
|
const filesAfter = await captureFileContents(managedFilePaths);
|
|
13589
13791
|
const changedFiles = managedFilePaths
|
|
13590
13792
|
.filter((filePath) => filesBefore[filePath] !== filesAfter[filePath])
|
|
13591
13793
|
.map((filePath) => toPosixPath(path.relative(workspaceRoot, filePath)));
|
|
13592
13794
|
|
|
13593
|
-
const rulesContent =
|
|
13594
|
-
filesAfter[scaffold.engineeringRulesPath] ??
|
|
13595
|
-
(await readFile(scaffold.engineeringRulesPath, "utf8"));
|
|
13596
13795
|
const techContent =
|
|
13597
13796
|
filesAfter[scaffold.techMdPath] ?? (await readFile(scaffold.techMdPath, "utf8"));
|
|
13598
13797
|
const productContent =
|
|
@@ -13600,8 +13799,6 @@ async function runBuildArchitecture(options) {
|
|
|
13600
13799
|
const architectureContent =
|
|
13601
13800
|
filesAfter[scaffold.architectureDocPath] ??
|
|
13602
13801
|
(await readFile(scaffold.architectureDocPath, "utf8"));
|
|
13603
|
-
const roadmapContent =
|
|
13604
|
-
filesAfter[scaffold.roadmapPath] ?? (await readFile(scaffold.roadmapPath, "utf8"));
|
|
13605
13802
|
|
|
13606
13803
|
const metadataPath = path.join(
|
|
13607
13804
|
workspaceRoot,
|
|
@@ -13611,36 +13808,13 @@ async function runBuildArchitecture(options) {
|
|
|
13611
13808
|
const metadata = buildArchitectureBuildMetadata({
|
|
13612
13809
|
platform,
|
|
13613
13810
|
researchMode,
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13621
|
-
extractTaggedMarkerAttribute(
|
|
13622
|
-
architectureContent,
|
|
13623
|
-
ARCHITECTURE_DOC_BLOCK_START_RE,
|
|
13624
|
-
"profile",
|
|
13625
|
-
) || "unknown",
|
|
13626
|
-
rulesProfileHash:
|
|
13627
|
-
extractTaggedMarkerAttribute(
|
|
13628
|
-
rulesContent,
|
|
13629
|
-
ENGINEERING_ARCHITECTURE_BLOCK_START_RE,
|
|
13630
|
-
"profile",
|
|
13631
|
-
) || "unknown",
|
|
13632
|
-
techSnapshotHash:
|
|
13633
|
-
extractTaggedMarkerAttribute(
|
|
13634
|
-
techContent,
|
|
13635
|
-
TECH_ARCHITECTURE_BLOCK_START_RE,
|
|
13636
|
-
"snapshot",
|
|
13637
|
-
) || "unknown",
|
|
13638
|
-
roadmapProfileHash:
|
|
13639
|
-
extractTaggedMarkerAttribute(
|
|
13640
|
-
roadmapContent,
|
|
13641
|
-
ROADMAP_FOUNDATION_BLOCK_START_RE,
|
|
13642
|
-
"profile",
|
|
13643
|
-
) || "unknown",
|
|
13811
|
+
managedDocs: [
|
|
13812
|
+
`${FOUNDATION_DOCS_DIR}/PRODUCT.md`,
|
|
13813
|
+
`${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md`,
|
|
13814
|
+
`${FOUNDATION_DOCS_DIR}/TECH.md`,
|
|
13815
|
+
`${FOUNDATION_ADR_DIR}/README.md`,
|
|
13816
|
+
`${FOUNDATION_ADR_DIR}/0000-template.md`,
|
|
13817
|
+
],
|
|
13644
13818
|
});
|
|
13645
13819
|
await mkdir(path.dirname(metadataPath), { recursive: true });
|
|
13646
13820
|
await writeFile(
|
|
@@ -13676,10 +13850,10 @@ async function runBuildArchitecture(options) {
|
|
|
13676
13850
|
console.log(`Adapter: ${adapter.binary}`);
|
|
13677
13851
|
console.log(`Workspace: ${toPosixPath(workspaceRoot)}`);
|
|
13678
13852
|
console.log(
|
|
13679
|
-
|
|
13853
|
+
`Managed docs: ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ${FOUNDATION_DOCS_DIR}/TECH.md`,
|
|
13680
13854
|
);
|
|
13681
13855
|
console.log(
|
|
13682
|
-
|
|
13856
|
+
`ADR scaffold: ${FOUNDATION_ADR_DIR}/README.md, ${FOUNDATION_ADR_DIR}/0000-template.md`,
|
|
13683
13857
|
);
|
|
13684
13858
|
console.log(`Skill bundle: ${skillBundle.join(", ")}`);
|
|
13685
13859
|
console.log(
|