@cubis/foundry 0.3.78 → 0.3.80

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.
Files changed (81) hide show
  1. package/dist/cli/build/commands.js +1 -1
  2. package/dist/cli/build/commands.js.map +1 -1
  3. package/dist/cli/core.js +752 -101
  4. package/dist/cli/core.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/cli/build/commands.ts +1 -1
  7. package/src/cli/core.ts +884 -114
  8. package/workflows/workflows/agent-environment-setup/generated/route-manifest.json +2 -2
  9. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/accessibility.toml +1 -1
  10. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/architecture.toml +2 -2
  11. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/backend.toml +1 -1
  12. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/create.toml +1 -1
  13. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/database.toml +1 -1
  14. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/debug.toml +1 -1
  15. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/devops.toml +1 -1
  16. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/implement-track.toml +1 -1
  17. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/migrate.toml +1 -1
  18. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/mobile.toml +1 -1
  19. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/onboard.toml +1 -1
  20. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/orchestrate.toml +1 -1
  21. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/plan.toml +1 -1
  22. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/refactor.toml +1 -1
  23. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/release.toml +1 -1
  24. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/review.toml +1 -1
  25. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/security.toml +1 -1
  26. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/spec.toml +1 -1
  27. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/test.toml +1 -1
  28. package/workflows/workflows/agent-environment-setup/platforms/antigravity/commands/vercel.toml +1 -1
  29. package/workflows/workflows/agent-environment-setup/platforms/antigravity/workflows/architecture.md +20 -15
  30. package/workflows/workflows/agent-environment-setup/platforms/antigravity/workflows/spec.md +2 -2
  31. package/workflows/workflows/agent-environment-setup/platforms/claude/workflows/architecture.md +20 -15
  32. package/workflows/workflows/agent-environment-setup/platforms/claude/workflows/spec.md +2 -2
  33. package/workflows/workflows/agent-environment-setup/platforms/codex/workflows/architecture.md +20 -15
  34. package/workflows/workflows/agent-environment-setup/platforms/codex/workflows/spec.md +2 -2
  35. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-accessibility.prompt.md +1 -1
  36. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-architecture.prompt.md +2 -2
  37. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-backend.prompt.md +1 -1
  38. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-create.prompt.md +1 -1
  39. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-database.prompt.md +1 -1
  40. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-debug.prompt.md +1 -1
  41. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-devops.prompt.md +1 -1
  42. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-implement-track.prompt.md +1 -1
  43. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-migrate.prompt.md +1 -1
  44. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-mobile.prompt.md +1 -1
  45. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-onboard.prompt.md +1 -1
  46. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-orchestrate.prompt.md +1 -1
  47. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-plan.prompt.md +1 -1
  48. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-refactor.prompt.md +1 -1
  49. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-release.prompt.md +1 -1
  50. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-review.prompt.md +1 -1
  51. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-security.prompt.md +1 -1
  52. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-spec.prompt.md +1 -1
  53. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-test.prompt.md +1 -1
  54. package/workflows/workflows/agent-environment-setup/platforms/copilot/prompts/workflow-vercel.prompt.md +1 -1
  55. package/workflows/workflows/agent-environment-setup/platforms/copilot/workflows/architecture.md +20 -15
  56. package/workflows/workflows/agent-environment-setup/platforms/copilot/workflows/spec.md +2 -2
  57. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/accessibility.toml +1 -1
  58. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/architecture.toml +2 -2
  59. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/backend.toml +1 -1
  60. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/create.toml +1 -1
  61. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/database.toml +1 -1
  62. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/debug.toml +1 -1
  63. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/devops.toml +1 -1
  64. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/implement-track.toml +1 -1
  65. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/migrate.toml +1 -1
  66. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/mobile.toml +1 -1
  67. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/onboard.toml +1 -1
  68. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/orchestrate.toml +1 -1
  69. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/plan.toml +1 -1
  70. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/refactor.toml +1 -1
  71. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/release.toml +1 -1
  72. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/review.toml +1 -1
  73. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/security.toml +1 -1
  74. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/spec.toml +1 -1
  75. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/test.toml +1 -1
  76. package/workflows/workflows/agent-environment-setup/platforms/gemini/commands/vercel.toml +1 -1
  77. package/workflows/workflows/agent-environment-setup/platforms/gemini/workflows/architecture.md +20 -15
  78. package/workflows/workflows/agent-environment-setup/platforms/gemini/workflows/spec.md +2 -2
  79. package/workflows/workflows/agent-environment-setup/shared/rules/STEERING.md +3 -3
  80. package/workflows/workflows/agent-environment-setup/shared/workflows/architecture.md +20 -15
  81. package/workflows/workflows/agent-environment-setup/shared/workflows/spec.md +2 -2
package/dist/cli/core.js CHANGED
@@ -27,8 +27,16 @@ const ENGINEERING_RULES_FILE_BLOCK_START_RE = /<!--\s*cbx:engineering:rules:star
27
27
  const ENGINEERING_RULES_FILE_BLOCK_END_RE = /<!--\s*cbx:engineering:rules:end\s*-->/g;
28
28
  const ENGINEERING_ARCHITECTURE_BLOCK_START_RE = /<!--\s*cbx:architecture:rules:start[^>]*-->/g;
29
29
  const ENGINEERING_ARCHITECTURE_BLOCK_END_RE = /<!--\s*cbx:architecture:rules:end\s*-->/g;
30
+ const PRODUCT_FOUNDATION_BLOCK_START_RE = /<!--\s*cbx:product:foundation:start[^>]*-->/g;
31
+ const PRODUCT_FOUNDATION_BLOCK_END_RE = /<!--\s*cbx:product:foundation:end\s*-->/g;
32
+ const ARCHITECTURE_DOC_BLOCK_START_RE = /<!--\s*cbx:architecture:doc:start[^>]*-->/g;
33
+ const ARCHITECTURE_DOC_BLOCK_END_RE = /<!--\s*cbx:architecture:doc:end\s*-->/g;
30
34
  const TECH_ARCHITECTURE_BLOCK_START_RE = /<!--\s*cbx:architecture:tech:start[^>]*-->/g;
31
35
  const TECH_ARCHITECTURE_BLOCK_END_RE = /<!--\s*cbx:architecture:tech:end\s*-->/g;
36
+ const ROADMAP_FOUNDATION_BLOCK_START_RE = /<!--\s*cbx:roadmap:foundation:start[^>]*-->/g;
37
+ const ROADMAP_FOUNDATION_BLOCK_END_RE = /<!--\s*cbx:roadmap:foundation:end\s*-->/g;
38
+ const FOUNDATION_DOCS_DIR = path.join("docs", "foundation");
39
+ const FOUNDATION_ADR_DIR = path.join(FOUNDATION_DOCS_DIR, "adr");
32
40
  const COPILOT_ALLOWED_SKILL_FRONTMATTER_KEYS = new Set([
33
41
  "compatibility",
34
42
  "description",
@@ -954,6 +962,154 @@ function buildArchitectureMermaid(snapshot) {
954
962
  }
955
963
  return lines.join("\n");
956
964
  }
965
+ function inferProductFoundationProfile(snapshot, specRoots = []) {
966
+ const appRoots = (snapshot.architectureByApp || [])
967
+ .map((item) => item.rootPath)
968
+ .filter((value) => value && value !== ".");
969
+ const primarySurfaces = appRoots.length > 0 ? appRoots : snapshot.topDirs.slice(0, 6);
970
+ const userPersonas = [];
971
+ if (snapshot.frameworks.includes("Flutter")) {
972
+ userPersonas.push("End users interacting through mobile or desktop app surfaces");
973
+ }
974
+ if (snapshot.frameworks.includes("Next.js") ||
975
+ snapshot.frameworks.includes("React") ||
976
+ snapshot.topDirs.includes("web")) {
977
+ userPersonas.push("Browser users and internal operators using web-facing flows");
978
+ }
979
+ if (snapshot.frameworks.includes("NestJS") || snapshot.topDirs.includes("api")) {
980
+ userPersonas.push("Internal services, operators, or partner systems consuming API boundaries");
981
+ }
982
+ if (userPersonas.length === 0) {
983
+ userPersonas.push("Project stakeholders are not obvious from the repo alone; refine personas from product context before major feature work.");
984
+ }
985
+ const coreJourneys = [];
986
+ if (specRoots.length > 0) {
987
+ coreJourneys.push(`Active implementation themes are reflected in current spec packs: ${specRoots.join(", ")}.`);
988
+ }
989
+ if (primarySurfaces.length > 0) {
990
+ coreJourneys.push(`Primary product surfaces currently live in: ${primarySurfaces.join(", ")}.`);
991
+ }
992
+ if (snapshot.isMcpServer || snapshot.mcpSignals.length > 0) {
993
+ coreJourneys.push("Tool-assisted and MCP-driven workflows are part of the operating model and should stay stable.");
994
+ }
995
+ if (coreJourneys.length === 0) {
996
+ coreJourneys.push("Repository evidence is thin; capture the primary user journeys here before scaling the codebase further.");
997
+ }
998
+ const successSignals = [
999
+ "Feature work should stay aligned to explicit user or operator value, not speculative abstractions.",
1000
+ "Architecture changes should reduce onboarding, debugging, and testing cost over time.",
1001
+ ];
1002
+ if (snapshot.cicdSignals.length > 0) {
1003
+ successSignals.push(`Delivery flows already rely on ${snapshot.cicdSignals.join(", ")} signals; keep release friction low for that pipeline.`);
1004
+ }
1005
+ return {
1006
+ productScope: snapshot.readmeExcerpt ||
1007
+ "No explicit product summary was detected from repo docs. Replace this with a concise product statement when better context exists.",
1008
+ primarySurfaces,
1009
+ userPersonas,
1010
+ coreJourneys,
1011
+ successSignals,
1012
+ };
1013
+ }
1014
+ function buildProductFoundationSection(snapshot, specRoots = []) {
1015
+ const profile = inferProductFoundationProfile(snapshot, specRoots);
1016
+ const hash = hashStableObject(profile);
1017
+ return [
1018
+ `<!-- cbx:product:foundation:start version=1 profile=${hash} -->`,
1019
+ "## Product Foundation (auto-managed)",
1020
+ "",
1021
+ "### Product Scope",
1022
+ profile.productScope,
1023
+ "",
1024
+ "### Primary Surfaces",
1025
+ ...(profile.primarySurfaces.length > 0
1026
+ ? profile.primarySurfaces.map((item) => `- ${item}`)
1027
+ : ["- No primary surfaces were detected automatically."]),
1028
+ "",
1029
+ "### Users and Operators",
1030
+ ...profile.userPersonas.map((item) => `- ${item}`),
1031
+ "",
1032
+ "### Core Journeys",
1033
+ ...profile.coreJourneys.map((item) => `- ${item}`),
1034
+ "",
1035
+ "### Success Signals",
1036
+ ...profile.successSignals.map((item) => `- ${item}`),
1037
+ "",
1038
+ "### Product Guardrails",
1039
+ "- Keep product intent stable across future features so agents do not optimize for the wrong user outcome.",
1040
+ "- Refresh this managed section when scope, personas, operating model, or success metrics change materially.",
1041
+ "<!-- cbx:product:foundation:end -->",
1042
+ "",
1043
+ ].join("\n");
1044
+ }
1045
+ function inferArchitectureDocProfile(snapshot, specRoots = []) {
1046
+ const contract = inferArchitectureContractProfile(snapshot);
1047
+ const architectureSignals = (snapshot.architectureByApp || []).map((item) => {
1048
+ const label = item.rootPath === "." ? "repo root" : item.rootPath;
1049
+ const signals = item.architectureSignals && item.architectureSignals.length > 0
1050
+ ? item.architectureSignals.join(", ")
1051
+ : "not enough signals to classify";
1052
+ return `${label}: ${signals}`;
1053
+ });
1054
+ const decisionAreas = [
1055
+ "Module boundaries and dependency direction",
1056
+ "Design-system ownership and reusable primitives",
1057
+ "Testing and validation expectations by runtime boundary",
1058
+ ];
1059
+ if (specRoots.length > 0) {
1060
+ decisionAreas.push(`Active specs that may influence upcoming architecture work: ${specRoots.join(", ")}.`);
1061
+ }
1062
+ return {
1063
+ style: contract.style,
1064
+ designSystemSource: contract.designSystemSource,
1065
+ moduleBoundaries: contract.moduleBoundaries,
1066
+ architectureSignals,
1067
+ decisionAreas,
1068
+ scalingConstraints: contract.scalingConstraints,
1069
+ testingStrategy: contract.testingStrategy,
1070
+ };
1071
+ }
1072
+ function buildArchitectureDocSection(snapshot, specRoots = []) {
1073
+ const profile = inferArchitectureDocProfile(snapshot, specRoots);
1074
+ const hash = hashStableObject(profile);
1075
+ return [
1076
+ `<!-- cbx:architecture:doc:start version=1 profile=${hash} -->`,
1077
+ "## Accepted Architecture Backbone (auto-managed)",
1078
+ "",
1079
+ "### System Overview",
1080
+ `- Accepted style: ${profile.style}.`,
1081
+ `- Design-system source of truth: ${profile.designSystemSource}`,
1082
+ "",
1083
+ "### Bounded Contexts and Module Boundaries",
1084
+ ...(profile.moduleBoundaries.length > 0
1085
+ ? profile.moduleBoundaries.map((item) => `- ${item}`)
1086
+ : ["- No strong top-level module boundaries were detected automatically."]),
1087
+ "",
1088
+ "### Architecture Signals by Surface",
1089
+ ...(profile.architectureSignals.length > 0
1090
+ ? profile.architectureSignals.map((item) => `- ${item}`)
1091
+ : ["- No app-level architecture signals were inferred from the repo scan."]),
1092
+ "",
1093
+ "### Decision Areas to Preserve",
1094
+ ...profile.decisionAreas.map((item) => `- ${item}`),
1095
+ "",
1096
+ "### Scalability and Reliability Notes",
1097
+ ...profile.scalingConstraints.map((item) => `- ${item}`),
1098
+ "",
1099
+ "### Testing and Operability",
1100
+ ...profile.testingStrategy.map((item) => `- ${item}`),
1101
+ "",
1102
+ "### ADR Linkage",
1103
+ "- Keep durable architecture decisions in `docs/adr/` and summarize the active decision set here.",
1104
+ "",
1105
+ "### Mermaid Diagram",
1106
+ "```mermaid",
1107
+ buildArchitectureDocMermaid(snapshot),
1108
+ "```",
1109
+ "<!-- cbx:architecture:doc:end -->",
1110
+ "",
1111
+ ].join("\n");
1112
+ }
957
1113
  function buildEngineeringArchitectureSection(snapshot) {
958
1114
  const profile = inferArchitectureContractProfile(snapshot);
959
1115
  const hash = hashStableObject(profile);
@@ -973,11 +1129,30 @@ function buildEngineeringArchitectureSection(snapshot) {
973
1129
  ...profile.testingStrategy.map((rule) => ` - ${rule}`),
974
1130
  "- Doc refresh policy:",
975
1131
  " - Update these managed sections when architecture, scale, boundaries, design-system rules, or testing strategy changes.",
976
- " - For non-trivial work, read this file before planning and read TECH.md next.",
1132
+ ` - 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.`,
977
1133
  "<!-- cbx:architecture:rules:end -->",
978
1134
  "",
979
1135
  ].join("\n");
980
1136
  }
1137
+ function buildArchitectureDocMermaid(snapshot) {
1138
+ const topDirs = snapshot.topDirs.slice(0, 5);
1139
+ const lines = [
1140
+ "flowchart LR",
1141
+ ' product["Product Intent"] --> rules["Engineering Rules"]',
1142
+ ' product --> arch["Architecture Backbone"]',
1143
+ ' arch --> tech["Current Tech Snapshot"]',
1144
+ ];
1145
+ if (topDirs.length > 0) {
1146
+ for (let index = 0; index < topDirs.length; index += 1) {
1147
+ const dir = topDirs[index];
1148
+ const nodeName = `D${index}`;
1149
+ lines.push(` arch --> ${nodeName}["${dir}/"]`);
1150
+ }
1151
+ }
1152
+ lines.push(' arch --> adr["docs/adr"]');
1153
+ lines.push(' product --> specs["docs/specs"]');
1154
+ return lines.join("\n");
1155
+ }
981
1156
  function buildTechArchitectureSection(snapshot) {
982
1157
  const profile = inferArchitectureContractProfile(snapshot);
983
1158
  const payload = {
@@ -1030,6 +1205,48 @@ function buildTechArchitectureSection(snapshot) {
1030
1205
  "",
1031
1206
  ].join("\n");
1032
1207
  }
1208
+ function buildRoadmapFoundationSection(snapshot, specRoots = []) {
1209
+ const payload = {
1210
+ topDirs: snapshot.topDirs,
1211
+ frameworks: snapshot.frameworks,
1212
+ specRoots,
1213
+ };
1214
+ const hash = hashStableObject(payload);
1215
+ const nowItems = specRoots.length > 0
1216
+ ? specRoots.map((item) => `Track active change planning in \`${item}\`.`)
1217
+ : [
1218
+ "No active spec packs detected. Create a spec pack before starting the next non-trivial feature or migration.",
1219
+ ];
1220
+ const nextItems = [];
1221
+ if (snapshot.frameworks.length > 0) {
1222
+ nextItems.push(`Keep shared conventions stable across the current stack: ${snapshot.frameworks.join(", ")}.`);
1223
+ }
1224
+ if (snapshot.cicdSignals.length > 0) {
1225
+ nextItems.push(`Preserve release compatibility with the detected delivery surfaces: ${snapshot.cicdSignals.join(", ")}.`);
1226
+ }
1227
+ if (nextItems.length === 0) {
1228
+ nextItems.push("Document the next scaling milestones here once product direction and architecture constraints are clearer.");
1229
+ }
1230
+ return [
1231
+ `<!-- cbx:roadmap:foundation:start version=1 profile=${hash} -->`,
1232
+ "## Delivery Backbone (auto-managed)",
1233
+ "",
1234
+ "### Now",
1235
+ ...nowItems.map((item) => `- ${item}`),
1236
+ "",
1237
+ "### Next",
1238
+ ...nextItems.map((item) => `- ${item}`),
1239
+ "",
1240
+ "### Later",
1241
+ "- Use this section for medium-term scaling themes, major migrations, or cross-team architecture investments.",
1242
+ "",
1243
+ "### Backbone Maintenance",
1244
+ `- 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.`,
1245
+ "- Link major roadmap themes back to specs and ADRs instead of burying them in chat-only planning.",
1246
+ "<!-- cbx:roadmap:foundation:end -->",
1247
+ "",
1248
+ ].join("\n");
1249
+ }
1033
1250
  function buildEngineeringRulesTemplate() {
1034
1251
  return [
1035
1252
  "# Engineering Rules",
@@ -1131,17 +1348,139 @@ function buildEngineeringRulesTemplate() {
1131
1348
  "",
1132
1349
  ].join("\n");
1133
1350
  }
1134
- function buildEngineeringRulesManagedBlock({ platform, engineeringRulesFilePath, techMdFilePath, ruleFilePath, }) {
1351
+ function buildProductTemplate(snapshot, specRoots = []) {
1352
+ return [
1353
+ "# Product",
1354
+ "",
1355
+ "This file is the durable product backbone for the project.",
1356
+ "",
1357
+ buildProductFoundationSection(snapshot, specRoots).trimEnd(),
1358
+ "",
1359
+ ].join("\n");
1360
+ }
1361
+ function buildArchitectureDocTemplate(snapshot, specRoots = []) {
1362
+ return [
1363
+ "# Architecture",
1364
+ "",
1365
+ "This file captures the accepted architecture backbone for the project.",
1366
+ "",
1367
+ buildArchitectureDocSection(snapshot, specRoots).trimEnd(),
1368
+ "",
1369
+ ].join("\n");
1370
+ }
1371
+ function buildRoadmapTemplate(snapshot, specRoots = []) {
1372
+ return [
1373
+ "# Roadmap",
1374
+ "",
1375
+ "This file captures the living delivery backbone for medium-term product and architecture work.",
1376
+ "",
1377
+ buildRoadmapFoundationSection(snapshot, specRoots).trimEnd(),
1378
+ "",
1379
+ ].join("\n");
1380
+ }
1381
+ function buildProductBuildSkeleton() {
1382
+ return [
1383
+ "# Product",
1384
+ "",
1385
+ "This file is managed by `cbx build architecture`.",
1386
+ "",
1387
+ "<!-- cbx:product:foundation:start version=1 profile=uninitialized -->",
1388
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1389
+ "<!-- cbx:product:foundation:end -->",
1390
+ "",
1391
+ ].join("\n");
1392
+ }
1393
+ function buildArchitectureBuildSkeleton() {
1394
+ return [
1395
+ "# Architecture",
1396
+ "",
1397
+ "This file is managed by `cbx build architecture`.",
1398
+ "",
1399
+ "<!-- cbx:architecture:doc:start version=1 profile=uninitialized -->",
1400
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1401
+ "<!-- cbx:architecture:doc:end -->",
1402
+ "",
1403
+ ].join("\n");
1404
+ }
1405
+ function buildTechBuildSkeleton() {
1406
+ return [
1407
+ "# TECH.md",
1408
+ "",
1409
+ "This file is managed by `cbx build architecture`.",
1410
+ "",
1411
+ "<!-- cbx:architecture:tech:start version=1 snapshot=uninitialized -->",
1412
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1413
+ "<!-- cbx:architecture:tech:end -->",
1414
+ "",
1415
+ ].join("\n");
1416
+ }
1417
+ function buildAdrReadme() {
1418
+ return [
1419
+ "# Architecture Decision Records",
1420
+ "",
1421
+ "Use this directory for durable decisions that future contributors and agents need to preserve.",
1422
+ "",
1423
+ "## When to add an ADR",
1424
+ "",
1425
+ "- Architecture style or boundary changes",
1426
+ "- Data model or persistence strategy changes",
1427
+ "- Deployment or scaling model changes",
1428
+ "- Design-system ownership or shared UX pattern changes",
1429
+ "",
1430
+ "## Suggested format",
1431
+ "",
1432
+ "1. Context",
1433
+ "2. Decision",
1434
+ "3. Consequences",
1435
+ "4. Validation",
1436
+ "",
1437
+ "Start with `0000-template.md` and create numbered follow-up ADRs for accepted decisions.",
1438
+ "",
1439
+ ].join("\n");
1440
+ }
1441
+ function buildAdrTemplate() {
1442
+ return [
1443
+ "# ADR 0000: Title",
1444
+ "",
1445
+ "## Status",
1446
+ "",
1447
+ "Proposed",
1448
+ "",
1449
+ "## Context",
1450
+ "",
1451
+ "- What problem or pressure led to this decision?",
1452
+ "",
1453
+ "## Decision",
1454
+ "",
1455
+ "- What is the chosen direction?",
1456
+ "",
1457
+ "## Consequences",
1458
+ "",
1459
+ "- What tradeoffs, benefits, or costs follow from this choice?",
1460
+ "",
1461
+ "## Validation",
1462
+ "",
1463
+ "- How will the team know this decision is working?",
1464
+ "",
1465
+ ].join("\n");
1466
+ }
1467
+ function buildEngineeringRulesManagedBlock({ platform, productFilePath, architectureFilePath, engineeringRulesFilePath, techMdFilePath, roadmapFilePath, ruleFilePath, }) {
1468
+ const productRef = toPosixPath(path.resolve(productFilePath));
1469
+ const architectureRef = toPosixPath(path.resolve(architectureFilePath));
1135
1470
  const engineeringRef = toPosixPath(path.resolve(engineeringRulesFilePath));
1136
1471
  const techRef = toPosixPath(path.resolve(techMdFilePath));
1472
+ const roadmapRef = toPosixPath(path.resolve(roadmapFilePath));
1137
1473
  const ruleRef = toPosixPath(path.resolve(ruleFilePath));
1138
1474
  return [
1139
1475
  `<!-- cbx:engineering:auto:start platform=${platform} version=1 -->`,
1140
1476
  "## Engineering Guardrails (auto-managed)",
1141
1477
  "Apply these before planning, coding, review, and release:",
1142
1478
  "",
1479
+ `- Product backbone: \`${productRef}\``,
1480
+ `- Accepted architecture: \`${architectureRef}\``,
1143
1481
  `- Required baseline: \`${engineeringRef}\``,
1144
1482
  `- Project tech map: \`${techRef}\``,
1483
+ `- Delivery roadmap: \`${roadmapRef}\``,
1145
1484
  `- Active platform rule file: \`${ruleRef}\``,
1146
1485
  "",
1147
1486
  "Hard policy:",
@@ -1149,7 +1488,7 @@ function buildEngineeringRulesManagedBlock({ platform, engineeringRulesFilePath,
1149
1488
  "2. Keep architecture simple (KISS) and avoid speculative work (YAGNI).",
1150
1489
  "3. Apply SOLID pragmatically to reduce change risk, not add ceremony.",
1151
1490
  "4. Use clear naming with focused responsibilities and explicit boundaries.",
1152
- "5. For non-trivial work, read ENGINEERING_RULES.md first and TECH.md next before planning or implementation.",
1491
+ `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.`,
1153
1492
  "6. Require validation evidence (lint/types/tests) before merge.",
1154
1493
  "7. Use Decision Log response style.",
1155
1494
  "8. Every Decision Log must include a `Skills Used` section listing skill, workflow, or agent names.",
@@ -1240,11 +1579,14 @@ async function upsertEngineeringRulesFile({ targetPath, template, overwrite = fa
1240
1579
  filePath: targetPath,
1241
1580
  };
1242
1581
  }
1243
- async function upsertEngineeringRulesBlock({ ruleFilePath, platform, engineeringRulesFilePath, techMdFilePath, dryRun = false, }) {
1582
+ async function upsertEngineeringRulesBlock({ ruleFilePath, platform, productFilePath, architectureFilePath, engineeringRulesFilePath, techMdFilePath, roadmapFilePath, dryRun = false, }) {
1244
1583
  const block = buildEngineeringRulesManagedBlock({
1245
1584
  platform,
1585
+ productFilePath,
1586
+ architectureFilePath,
1246
1587
  engineeringRulesFilePath,
1247
1588
  techMdFilePath,
1589
+ roadmapFilePath,
1248
1590
  ruleFilePath,
1249
1591
  });
1250
1592
  const exists = await pathExists(ruleFilePath);
@@ -1313,6 +1655,16 @@ async function upsertTaggedSectionInFile({ targetPath, initialContent, block, st
1313
1655
  nextContent =
1314
1656
  trimmed.length > 0 ? `${trimmed}\n\n${block}\n` : `${block}\n`;
1315
1657
  }
1658
+ if (!exists) {
1659
+ if (!dryRun) {
1660
+ await mkdir(path.dirname(targetPath), { recursive: true });
1661
+ await writeFile(targetPath, nextContent, "utf8");
1662
+ }
1663
+ return {
1664
+ action: dryRun ? "would-create" : "created",
1665
+ filePath: targetPath,
1666
+ };
1667
+ }
1316
1668
  if (nextContent === original) {
1317
1669
  return {
1318
1670
  action: "unchanged",
@@ -1334,20 +1686,41 @@ async function upsertTaggedSectionInFile({ targetPath, initialContent, block, st
1334
1686
  filePath: targetPath,
1335
1687
  };
1336
1688
  }
1337
- function buildArchitectureBuildMetadata({ platform, researchMode, rulesProfileHash, techSnapshotHash, }) {
1689
+ function buildArchitectureBuildMetadata({ platform, researchMode, managedDocs, }) {
1338
1690
  return {
1339
- schemaVersion: 1,
1691
+ schemaVersion: 3,
1340
1692
  generatedBy: "cbx build architecture",
1341
1693
  generatedAt: new Date().toISOString(),
1342
1694
  platform,
1343
1695
  researchMode,
1344
- rulesProfileHash,
1345
- techSnapshotHash,
1696
+ managedDocs,
1346
1697
  };
1347
1698
  }
1348
- async function ensureArchitectureDocScaffold({ workspaceRoot, snapshot, overwrite = false, dryRun = false, }) {
1699
+ async function ensureArchitectureDocScaffold({ workspaceRoot, snapshot, specRoots = [], overwrite = false, dryRun = false, }) {
1700
+ const productPath = path.join(workspaceRoot, "PRODUCT.md");
1701
+ const architectureDocPath = path.join(workspaceRoot, "ARCHITECTURE.md");
1349
1702
  const engineeringRulesPath = path.join(workspaceRoot, "ENGINEERING_RULES.md");
1350
1703
  const techMdPath = path.join(workspaceRoot, "TECH.md");
1704
+ const roadmapPath = path.join(workspaceRoot, "ROADMAP.md");
1705
+ const adrDir = path.join(workspaceRoot, "docs", "adr");
1706
+ const adrReadmePath = path.join(adrDir, "README.md");
1707
+ const adrTemplatePath = path.join(adrDir, "0000-template.md");
1708
+ const productResult = await upsertTaggedSectionInFile({
1709
+ targetPath: productPath,
1710
+ initialContent: `${buildProductTemplate(snapshot, specRoots)}\n`,
1711
+ block: buildProductFoundationSection(snapshot, specRoots),
1712
+ startPattern: PRODUCT_FOUNDATION_BLOCK_START_RE,
1713
+ endPattern: PRODUCT_FOUNDATION_BLOCK_END_RE,
1714
+ dryRun,
1715
+ });
1716
+ const architectureDocResult = await upsertTaggedSectionInFile({
1717
+ targetPath: architectureDocPath,
1718
+ initialContent: `${buildArchitectureDocTemplate(snapshot, specRoots)}\n`,
1719
+ block: buildArchitectureDocSection(snapshot, specRoots),
1720
+ startPattern: ARCHITECTURE_DOC_BLOCK_START_RE,
1721
+ endPattern: ARCHITECTURE_DOC_BLOCK_END_RE,
1722
+ dryRun,
1723
+ });
1351
1724
  const rulesTemplate = buildEngineeringRulesTemplate();
1352
1725
  const rulesFileResult = await upsertEngineeringRulesFile({
1353
1726
  targetPath: engineeringRulesPath,
@@ -1378,13 +1751,115 @@ async function ensureArchitectureDocScaffold({ workspaceRoot, snapshot, overwrit
1378
1751
  endPattern: TECH_ARCHITECTURE_BLOCK_END_RE,
1379
1752
  dryRun,
1380
1753
  });
1754
+ const roadmapResult = await upsertTaggedSectionInFile({
1755
+ targetPath: roadmapPath,
1756
+ initialContent: `${buildRoadmapTemplate(snapshot, specRoots)}\n`,
1757
+ block: buildRoadmapFoundationSection(snapshot, specRoots),
1758
+ startPattern: ROADMAP_FOUNDATION_BLOCK_START_RE,
1759
+ endPattern: ROADMAP_FOUNDATION_BLOCK_END_RE,
1760
+ dryRun,
1761
+ });
1762
+ const adrReadmeResult = await writeTextFile({
1763
+ targetPath: adrReadmePath,
1764
+ content: `${buildAdrReadme()}\n`,
1765
+ overwrite,
1766
+ dryRun,
1767
+ });
1768
+ const adrTemplateResult = await writeTextFile({
1769
+ targetPath: adrTemplatePath,
1770
+ content: `${buildAdrTemplate()}\n`,
1771
+ overwrite,
1772
+ dryRun,
1773
+ });
1381
1774
  return {
1775
+ productPath,
1776
+ architectureDocPath,
1382
1777
  engineeringRulesPath,
1383
1778
  techMdPath,
1779
+ roadmapPath,
1780
+ adrReadmePath,
1781
+ adrTemplatePath,
1782
+ productResult,
1783
+ architectureDocResult,
1384
1784
  rulesFileResult,
1385
1785
  rulesArchitectureResult,
1386
1786
  techResult,
1387
1787
  techArchitectureResult,
1788
+ roadmapResult,
1789
+ adrReadmeResult,
1790
+ adrTemplateResult,
1791
+ };
1792
+ }
1793
+ async function ensureArchitectureBuildScaffold({ workspaceRoot, dryRun = false, }) {
1794
+ const foundationRoot = path.join(workspaceRoot, FOUNDATION_DOCS_DIR);
1795
+ const productPath = path.join(foundationRoot, "PRODUCT.md");
1796
+ const architectureDocPath = path.join(foundationRoot, "ARCHITECTURE.md");
1797
+ const techMdPath = path.join(foundationRoot, "TECH.md");
1798
+ const adrDir = path.join(workspaceRoot, FOUNDATION_ADR_DIR);
1799
+ const adrReadmePath = path.join(adrDir, "README.md");
1800
+ const adrTemplatePath = path.join(adrDir, "0000-template.md");
1801
+ const productResult = await upsertTaggedSectionInFile({
1802
+ targetPath: productPath,
1803
+ initialContent: `${buildProductBuildSkeleton()}\n`,
1804
+ block: [
1805
+ "<!-- cbx:product:foundation:start version=1 profile=uninitialized -->",
1806
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1807
+ "<!-- cbx:product:foundation:end -->",
1808
+ "",
1809
+ ].join("\n"),
1810
+ startPattern: PRODUCT_FOUNDATION_BLOCK_START_RE,
1811
+ endPattern: PRODUCT_FOUNDATION_BLOCK_END_RE,
1812
+ dryRun,
1813
+ });
1814
+ const architectureDocResult = await upsertTaggedSectionInFile({
1815
+ targetPath: architectureDocPath,
1816
+ initialContent: `${buildArchitectureBuildSkeleton()}\n`,
1817
+ block: [
1818
+ "<!-- cbx:architecture:doc:start version=1 profile=uninitialized -->",
1819
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1820
+ "<!-- cbx:architecture:doc:end -->",
1821
+ "",
1822
+ ].join("\n"),
1823
+ startPattern: ARCHITECTURE_DOC_BLOCK_START_RE,
1824
+ endPattern: ARCHITECTURE_DOC_BLOCK_END_RE,
1825
+ dryRun,
1826
+ });
1827
+ const techResult = await upsertTaggedSectionInFile({
1828
+ targetPath: techMdPath,
1829
+ initialContent: `${buildTechBuildSkeleton()}\n`,
1830
+ block: [
1831
+ "<!-- cbx:architecture:tech:start version=1 snapshot=uninitialized -->",
1832
+ "Replace this managed section by running `cbx build architecture --platform <codex|claude|gemini|copilot>`.",
1833
+ "<!-- cbx:architecture:tech:end -->",
1834
+ "",
1835
+ ].join("\n"),
1836
+ startPattern: TECH_ARCHITECTURE_BLOCK_START_RE,
1837
+ endPattern: TECH_ARCHITECTURE_BLOCK_END_RE,
1838
+ dryRun,
1839
+ });
1840
+ const adrReadmeResult = await writeTextFile({
1841
+ targetPath: adrReadmePath,
1842
+ content: `${buildAdrReadme()}\n`,
1843
+ overwrite: false,
1844
+ dryRun,
1845
+ });
1846
+ const adrTemplateResult = await writeTextFile({
1847
+ targetPath: adrTemplatePath,
1848
+ content: `${buildAdrTemplate()}\n`,
1849
+ overwrite: false,
1850
+ dryRun,
1851
+ });
1852
+ return {
1853
+ productPath,
1854
+ architectureDocPath,
1855
+ techMdPath,
1856
+ adrReadmePath,
1857
+ adrTemplatePath,
1858
+ productResult,
1859
+ architectureDocResult,
1860
+ techResult,
1861
+ adrReadmeResult,
1862
+ adrTemplateResult,
1388
1863
  };
1389
1864
  }
1390
1865
  function normalizeTechPackageName(value) {
@@ -6958,14 +7433,6 @@ async function performWorkflowInstall(options, { postmanSelectionOverride = null
6958
7433
  dryRun,
6959
7434
  cwd,
6960
7435
  });
6961
- const engineeringArtifactsResult = await upsertEngineeringArtifacts({
6962
- platform,
6963
- scope: ruleScope,
6964
- overwrite: false,
6965
- dryRun,
6966
- skipTech: false,
6967
- cwd,
6968
- });
6969
7436
  const postmanSetupResult = await configurePostmanInstallArtifacts({
6970
7437
  platform,
6971
7438
  scope,
@@ -7007,7 +7474,7 @@ async function performWorkflowInstall(options, { postmanSelectionOverride = null
7007
7474
  bundleId,
7008
7475
  installResult,
7009
7476
  syncResult,
7010
- engineeringArtifactsResult,
7477
+ engineeringArtifactsResult: null,
7011
7478
  postmanSetupResult,
7012
7479
  terminalVerificationRuleResult,
7013
7480
  };
@@ -7035,10 +7502,7 @@ async function runWorkflowInstall(options) {
7035
7502
  dryRun: result.dryRun,
7036
7503
  });
7037
7504
  printRuleSyncResult(result.syncResult);
7038
- printInstallEngineeringSummary({
7039
- engineeringResults: result.engineeringArtifactsResult.engineeringResults,
7040
- techResult: result.engineeringArtifactsResult.techResult,
7041
- });
7505
+ printInstallDocumentationNotice();
7042
7506
  printPostmanSetupSummary({
7043
7507
  postmanSetup: result.postmanSetupResult,
7044
7508
  });
@@ -9897,6 +10361,11 @@ function printInstallEngineeringSummary({ engineeringResults, techResult }) {
9897
10361
  console.log(`- TECH scan files: ${techResult.snapshot.scannedFiles}`);
9898
10362
  }
9899
10363
  }
10364
+ function printInstallDocumentationNotice() {
10365
+ console.log("\nProject backbone docs:");
10366
+ console.log("- Install only wires the rule references and workflow assets.");
10367
+ console.log(`- 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.`);
10368
+ }
9900
10369
  async function upsertEngineeringArtifacts({ platform, scope, overwrite = false, skipTech = false, dryRun = false, cwd = process.cwd(), }) {
9901
10370
  const ruleFilePath = await resolveRuleFilePath(platform, scope, cwd);
9902
10371
  if (!ruleFilePath)
@@ -9906,10 +10375,10 @@ async function upsertEngineeringArtifacts({ platform, scope, overwrite = false,
9906
10375
  const scaffold = await ensureArchitectureDocScaffold({
9907
10376
  workspaceRoot,
9908
10377
  snapshot,
10378
+ specRoots: [],
9909
10379
  overwrite,
9910
10380
  dryRun,
9911
10381
  });
9912
- const techMdPath = path.join(workspaceRoot, "TECH.md");
9913
10382
  const targets = [{ ruleFilePath }];
9914
10383
  if (scope === "global") {
9915
10384
  const workspaceRuleFile = await resolveWorkspaceRuleFileForGlobalScope(platform, cwd);
@@ -9924,8 +10393,11 @@ async function upsertEngineeringArtifacts({ platform, scope, overwrite = false,
9924
10393
  const blockResult = await upsertEngineeringRulesBlock({
9925
10394
  ruleFilePath: target.ruleFilePath,
9926
10395
  platform,
10396
+ productFilePath: scaffold.productPath,
10397
+ architectureFilePath: scaffold.architectureDocPath,
9927
10398
  engineeringRulesFilePath: scaffold.engineeringRulesPath,
9928
- techMdFilePath: techMdPath,
10399
+ techMdFilePath: scaffold.techMdPath,
10400
+ roadmapFilePath: scaffold.roadmapPath,
9929
10401
  dryRun,
9930
10402
  });
9931
10403
  engineeringResults.push({
@@ -10043,6 +10515,61 @@ async function listSpecPackRoots(workspaceRoot) {
10043
10515
  .sort((a, b) => a.localeCompare(b))
10044
10516
  .slice(0, 8);
10045
10517
  }
10518
+ async function resolveArchitectureInspectionAnchors(workspaceRoot, snapshot, specRoots) {
10519
+ const seen = new Set();
10520
+ const ordered = [];
10521
+ const pushCandidate = async (relativePath) => {
10522
+ const normalized = toPosixPath(relativePath);
10523
+ if (!normalized || seen.has(normalized))
10524
+ return;
10525
+ if (!(await pathExists(path.join(workspaceRoot, relativePath))))
10526
+ return;
10527
+ seen.add(normalized);
10528
+ ordered.push(normalized);
10529
+ };
10530
+ for (const candidate of [
10531
+ "README.md",
10532
+ "package.json",
10533
+ "pubspec.yaml",
10534
+ "go.mod",
10535
+ "pyproject.toml",
10536
+ "Cargo.toml",
10537
+ "Dockerfile",
10538
+ "docker-compose.yml",
10539
+ "docker-compose.yaml",
10540
+ "compose.yaml",
10541
+ "cbx_config.json",
10542
+ ".vscode/mcp.json",
10543
+ ".gemini/settings.json",
10544
+ ]) {
10545
+ await pushCandidate(candidate);
10546
+ }
10547
+ for (const specRoot of specRoots.slice(0, 4)) {
10548
+ await pushCandidate(specRoot);
10549
+ }
10550
+ for (const app of snapshot.architectureByApp || []) {
10551
+ if (!app?.rootPath || app.rootPath === ".")
10552
+ continue;
10553
+ await pushCandidate(app.rootPath);
10554
+ for (const child of [
10555
+ "README.md",
10556
+ "src",
10557
+ "lib",
10558
+ "app",
10559
+ "prisma",
10560
+ "migrations",
10561
+ "test",
10562
+ "tests",
10563
+ "docs",
10564
+ ]) {
10565
+ await pushCandidate(path.join(app.rootPath, child));
10566
+ }
10567
+ }
10568
+ for (const dir of snapshot.topDirs || []) {
10569
+ await pushCandidate(dir);
10570
+ }
10571
+ return ordered.slice(0, 18);
10572
+ }
10046
10573
  function resolveArchitectureConditionalSkills(snapshot, specRoots, researchMode) {
10047
10574
  const conditional = [];
10048
10575
  const frameworks = new Set(snapshot.frameworks || []);
@@ -10087,9 +10614,12 @@ async function resolveArchitectureSkillPathHints(platform, cwd, skillIds) {
10087
10614
  .map((skillId) => path.join(skillsDir, skillId, "SKILL.md"))
10088
10615
  .map((filePath) => toPosixPath(path.relative(findWorkspaceRoot(cwd), filePath)));
10089
10616
  }
10090
- function buildArchitecturePrompt({ platform, workspaceRoot, snapshot, specRoots, researchMode, coreSkills, conditionalSkills, skillPathHints, }) {
10091
- const rulesPath = "ENGINEERING_RULES.md";
10092
- const techPath = "TECH.md";
10617
+ function buildArchitecturePrompt({ platform, workspaceRoot, snapshot, specRoots, inspectionAnchors, researchMode, coreSkills, conditionalSkills, skillPathHints, }) {
10618
+ const productPath = `${FOUNDATION_DOCS_DIR}/PRODUCT.md`;
10619
+ const architecturePath = `${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md`;
10620
+ const techPath = `${FOUNDATION_DOCS_DIR}/TECH.md`;
10621
+ const adrReadmePath = `${FOUNDATION_ADR_DIR}/README.md`;
10622
+ const adrTemplatePath = `${FOUNDATION_ADR_DIR}/0000-template.md`;
10093
10623
  const architectureSignals = snapshot.architectureByApp
10094
10624
  .filter((item) => (item.architectureSignals || []).length > 0)
10095
10625
  .map((item) => {
@@ -10100,9 +10630,9 @@ function buildArchitecturePrompt({ platform, workspaceRoot, snapshot, specRoots,
10100
10630
  `You are running inside ${platform}.`,
10101
10631
  "",
10102
10632
  "Objective:",
10103
- `- Inspect the repository at ${toPosixPath(workspaceRoot)} and refresh the managed architecture sections in ${rulesPath} and ${techPath}.`,
10104
- "- Keep ENGINEERING_RULES.md normative and TECH.md descriptive.",
10105
- "- Preserve manual content outside the managed `cbx:architecture:*` markers.",
10633
+ `- Inspect the repository at ${toPosixPath(workspaceRoot)} and author or refresh the core foundation docs in ${productPath}, ${architecturePath}, ${techPath}, ${adrReadmePath}, and ${adrTemplatePath}.`,
10634
+ "- The content should be primarily AI-authored from repository inspection, not copied from placeholder scaffolding.",
10635
+ "- Preserve manual content outside the managed `cbx:*` markers.",
10106
10636
  "",
10107
10637
  "Required skill bundle:",
10108
10638
  `- Load these exact skill IDs first: ${coreSkills.map((skillId) => `\`${skillId}\``).join(", ")}`,
@@ -10121,24 +10651,33 @@ function buildArchitecturePrompt({ platform, workspaceRoot, snapshot, specRoots,
10121
10651
  architectureSignals.length > 0
10122
10652
  ? `- Architecture signals: ${architectureSignals.join(" | ")}`
10123
10653
  : "- Architecture signals: none confidently inferred from the repo scan",
10654
+ `- Entry points: ${snapshot.entryPoints.length > 0 ? snapshot.entryPoints.slice(0, 8).join(" | ") : "none detected"}`,
10655
+ `- Key scripts: ${snapshot.keyScripts.length > 0 ? snapshot.keyScripts.slice(0, 8).map((item) => `${item.name}=${item.command}`).join(" | ") : "none detected"}`,
10656
+ `- Inspection anchors: ${inspectionAnchors.length > 0 ? inspectionAnchors.join(", ") : "no concrete anchors detected; inspect the repo root, main source trees, and manifest files manually"}`,
10124
10657
  "",
10125
10658
  "Execution contract:",
10126
- "1. Read ENGINEERING_RULES.md first if present, then read TECH.md.",
10127
- "2. Inspect the repo before making architecture claims.",
10128
- "3. Update only the content between the existing `cbx:architecture:rules` and `cbx:architecture:tech` markers.",
10129
- "4. Keep the marker lines themselves intact, including their hash metadata.",
10130
- "5. In ENGINEERING_RULES.md, state architecture style, dependency rules, feature or module structure rules, design-system source of truth, testability expectations, and doc refresh policy.",
10131
- "6. In TECH.md, update architecture snapshot, module or app topology, flow narratives, Mermaid diagrams, and scaling or deployment notes.",
10659
+ "1. Inspect the repository first before writing any backbone doc content. Derive structure, product surfaces, runtime boundaries, and technical constraints from the actual codebase.",
10660
+ "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.",
10661
+ "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.",
10662
+ `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.`,
10663
+ `5. Replace or update only the content between the existing managed markers in ${productPath}, ${architecturePath}, and ${techPath}. Do not append a second marker block.`,
10664
+ `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.`,
10665
+ `7. In ${architecturePath}, write a lean but detailed architecture backbone in a pragmatic arc42/C4 style: system purpose and constraints, 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.`,
10666
+ `8. 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.`,
10667
+ "9. Every major claim should be grounded in repository evidence. Mention concrete repo paths in the docs when a structural claim would otherwise be ambiguous.",
10668
+ "10. Avoid placeholder filler, generic checklists, and duplicated content across files. Each doc should have a clear job.",
10669
+ "11. Do not create ROADMAP.md, ENGINEERING_RULES.md, or other extra docs unless the prompt explicitly asks for them.",
10132
10670
  researchMode === "never"
10133
- ? "7. Stay repo-only. Do not use outside research."
10134
- : "7. Use repo evidence first. Use official docs when needed. Treat Reddit or community sources only as labeled secondary evidence.",
10671
+ ? "12. Stay repo-only. Do not use outside research."
10672
+ : "12. Use repo evidence first. Use official docs when needed. Treat Reddit or community sources only as labeled secondary evidence.",
10135
10673
  researchMode === "always"
10136
- ? "8. Include an external research evidence subsection in TECH.md with clearly labeled primary and secondary evidence."
10137
- : "8. Include external research notes only if they materially informed the architecture update.",
10138
- "9. If the project clearly follows Clean Architecture, feature-first modules, or another stable structure, make that explicit so future implementation stays consistent.",
10674
+ ? `13. Include an external research evidence subsection in ${techPath} with clearly labeled primary and secondary evidence.`
10675
+ : "13. Include external research notes only if they materially informed the architecture update.",
10676
+ `14. 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.`,
10677
+ `15. Ensure ${adrReadmePath} and ${adrTemplatePath} exist as ADR entrypoints, but keep them lean.`,
10139
10678
  "",
10140
10679
  "Return one JSON object on the last line with this shape:",
10141
- '{"files_written":["ENGINEERING_RULES.md","TECH.md"],"research_used":false,"gaps":[],"next_actions":[]}',
10680
+ `{"files_written":["${productPath}","${architecturePath}","${techPath}","${adrReadmePath}","${adrTemplatePath}"],"research_used":false,"gaps":[],"next_actions":[]}`,
10142
10681
  "",
10143
10682
  "Do not emit placeholder TODOs in the managed sections.",
10144
10683
  ].join("\n");
@@ -10167,6 +10706,73 @@ async function execFileCapture(command, args, options = {}) {
10167
10706
  };
10168
10707
  }
10169
10708
  }
10709
+ async function spawnCapture(command, args, options = {}) {
10710
+ const { cwd, env, streamOutput = false } = options;
10711
+ return await new Promise((resolve, reject) => {
10712
+ let stdout = "";
10713
+ let stderr = "";
10714
+ const child = spawn(command, args, {
10715
+ cwd,
10716
+ env,
10717
+ stdio: ["ignore", "pipe", "pipe"],
10718
+ });
10719
+ child.stdout.on("data", (chunk) => {
10720
+ const text = chunk.toString();
10721
+ stdout += text;
10722
+ if (streamOutput)
10723
+ process.stdout.write(text);
10724
+ });
10725
+ child.stderr.on("data", (chunk) => {
10726
+ const text = chunk.toString();
10727
+ stderr += text;
10728
+ if (streamOutput)
10729
+ process.stderr.write(text);
10730
+ });
10731
+ child.on("error", (error) => {
10732
+ if (error?.code === "ENOENT") {
10733
+ reject(new Error(`Required CLI '${command}' is not installed or not on PATH.`));
10734
+ return;
10735
+ }
10736
+ reject(error);
10737
+ });
10738
+ child.on("close", (code) => {
10739
+ resolve({
10740
+ ok: code === 0,
10741
+ stdout,
10742
+ stderr,
10743
+ code: code ?? 1,
10744
+ });
10745
+ });
10746
+ });
10747
+ }
10748
+ function explainArchitectureBuildFailure(platform, execution) {
10749
+ const combined = String(`${execution.stderr || ""}\n${execution.stdout || ""}`.trim());
10750
+ const notes = [];
10751
+ if (platform === "gemini") {
10752
+ if (combined.includes("Error during discovery for MCP server") ||
10753
+ combined.includes("[MCP error]")) {
10754
+ notes.push("Gemini CLI is failing while loading MCP servers from your Gemini settings. Start the required MCP runtime(s) first or disable the broken server entries in `.gemini/settings.json` before retrying.");
10755
+ }
10756
+ if (combined.includes("cloudaicompanion.companions.generateChat") ||
10757
+ combined.includes("PERMISSION_DENIED") ||
10758
+ combined.includes("403")) {
10759
+ notes.push("Gemini CLI reached Google auth, but the active account or project cannot generate chat content. Re-authenticate Gemini CLI with a permitted account or configure a supported Gemini API credential and project before retrying.");
10760
+ }
10761
+ }
10762
+ if (platform === "claude" && combined.includes("permission")) {
10763
+ notes.push("Claude CLI appears to be blocked by its own permission model. Re-run in a Claude environment that allows non-interactive edits for this workspace.");
10764
+ }
10765
+ if (notes.length === 0) {
10766
+ return `Architecture build failed via ${platform}. ${combined}`.trim();
10767
+ }
10768
+ return [
10769
+ `Architecture build failed via ${platform}.`,
10770
+ ...notes.map((note) => `- ${note}`),
10771
+ combined ? `Raw CLI output:\n${combined}` : "",
10772
+ ]
10773
+ .filter(Boolean)
10774
+ .join("\n");
10775
+ }
10170
10776
  async function probeArchitectureAdapter(platform, cwd) {
10171
10777
  if (platform === "codex") {
10172
10778
  const help = await execFileCapture("codex", ["exec", "--help"], { cwd });
@@ -10242,7 +10848,7 @@ async function probeArchitectureAdapter(platform, cwd) {
10242
10848
  },
10243
10849
  };
10244
10850
  }
10245
- function normalizeArchitectureResult({ stdout, workspaceRoot, rulesPath, techPath, researchMode, }) {
10851
+ function normalizeArchitectureResult({ stdout, workspaceRoot, researchMode, changedFiles = [], }) {
10246
10852
  const trimmed = String(stdout || "").trim();
10247
10853
  if (trimmed) {
10248
10854
  const lastLine = trimmed.split(/\r?\n/).pop();
@@ -10251,9 +10857,11 @@ function normalizeArchitectureResult({ stdout, workspaceRoot, rulesPath, techPat
10251
10857
  const parsed = JSON.parse(lastLine);
10252
10858
  return {
10253
10859
  outputRoot: workspaceRoot,
10254
- filesWritten: Array.isArray(parsed.files_written)
10255
- ? parsed.files_written
10256
- : [rulesPath, techPath],
10860
+ filesWritten: changedFiles.length > 0
10861
+ ? changedFiles
10862
+ : Array.isArray(parsed.files_written)
10863
+ ? parsed.files_written
10864
+ : [],
10257
10865
  researchUsed: typeof parsed.research_used === "boolean"
10258
10866
  ? parsed.research_used
10259
10867
  : researchMode === "always",
@@ -10271,55 +10879,72 @@ function normalizeArchitectureResult({ stdout, workspaceRoot, rulesPath, techPat
10271
10879
  }
10272
10880
  return {
10273
10881
  outputRoot: workspaceRoot,
10274
- filesWritten: [rulesPath, techPath],
10882
+ filesWritten: changedFiles,
10275
10883
  researchUsed: researchMode === "always",
10276
10884
  gaps: [],
10277
10885
  nextActions: [],
10278
10886
  rawOutput: trimmed,
10279
10887
  };
10280
10888
  }
10889
+ async function captureFileContents(filePaths) {
10890
+ const snapshot = {};
10891
+ for (const filePath of filePaths) {
10892
+ if (await pathExists(filePath)) {
10893
+ snapshot[filePath] = await readFile(filePath, "utf8");
10894
+ }
10895
+ else {
10896
+ snapshot[filePath] = null;
10897
+ }
10898
+ }
10899
+ return snapshot;
10900
+ }
10281
10901
  async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
10282
- const rulesPath = path.join(workspaceRoot, "ENGINEERING_RULES.md");
10283
- const techPath = path.join(workspaceRoot, "TECH.md");
10902
+ const productPath = path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md");
10903
+ const architecturePath = path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "ARCHITECTURE.md");
10904
+ const techPath = path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md");
10905
+ const adrReadmePath = path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md");
10284
10906
  const metadataPath = path.join(workspaceRoot, ".cbx", ARCHITECTURE_BUILD_METADATA_FILENAME);
10285
- const rulesExists = await pathExists(rulesPath);
10907
+ const productExists = await pathExists(productPath);
10908
+ const architectureExists = await pathExists(architecturePath);
10286
10909
  const techExists = await pathExists(techPath);
10287
- const expectedRulesHash = hashStableObject(inferArchitectureContractProfile(snapshot));
10288
- const expectedTechHash = hashStableObject({
10289
- style: inferArchitectureContractProfile(snapshot).style,
10290
- topDirs: snapshot.topDirs,
10291
- frameworks: snapshot.frameworks,
10292
- architectureByApp: snapshot.architectureByApp,
10293
- });
10910
+ const adrReadmeExists = await pathExists(adrReadmePath);
10294
10911
  const findings = [];
10295
- let actualRulesHash = null;
10912
+ let actualProductHash = null;
10913
+ let actualArchitectureHash = null;
10296
10914
  let actualTechHash = null;
10297
- if (!rulesExists) {
10298
- findings.push("ENGINEERING_RULES.md is missing.");
10915
+ if (!productExists) {
10916
+ findings.push(`${FOUNDATION_DOCS_DIR}/PRODUCT.md is missing.`);
10299
10917
  }
10300
10918
  else {
10301
- const content = await readFile(rulesPath, "utf8");
10302
- actualRulesHash = extractTaggedMarkerAttribute(content, ENGINEERING_ARCHITECTURE_BLOCK_START_RE, "profile");
10303
- if (!actualRulesHash) {
10304
- findings.push("ENGINEERING_RULES.md is missing the managed architecture contract block.");
10919
+ const content = await readFile(productPath, "utf8");
10920
+ actualProductHash = extractTaggedMarkerAttribute(content, PRODUCT_FOUNDATION_BLOCK_START_RE, "profile");
10921
+ if (!actualProductHash) {
10922
+ findings.push(`${FOUNDATION_DOCS_DIR}/PRODUCT.md is missing the managed product foundation block.`);
10305
10923
  }
10306
- else if (actualRulesHash !== expectedRulesHash) {
10307
- findings.push(`ENGINEERING_RULES.md architecture profile is stale (expected ${expectedRulesHash}, found ${actualRulesHash}).`);
10924
+ }
10925
+ if (!architectureExists) {
10926
+ findings.push(`${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md is missing.`);
10927
+ }
10928
+ else {
10929
+ const content = await readFile(architecturePath, "utf8");
10930
+ actualArchitectureHash = extractTaggedMarkerAttribute(content, ARCHITECTURE_DOC_BLOCK_START_RE, "profile");
10931
+ if (!actualArchitectureHash) {
10932
+ findings.push(`${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md is missing the managed architecture backbone block.`);
10308
10933
  }
10309
10934
  }
10310
10935
  if (!techExists) {
10311
- findings.push("TECH.md is missing.");
10936
+ findings.push(`${FOUNDATION_DOCS_DIR}/TECH.md is missing.`);
10312
10937
  }
10313
10938
  else {
10314
10939
  const content = await readFile(techPath, "utf8");
10315
10940
  actualTechHash = extractTaggedMarkerAttribute(content, TECH_ARCHITECTURE_BLOCK_START_RE, "snapshot");
10316
10941
  if (!actualTechHash) {
10317
- findings.push("TECH.md is missing the managed architecture snapshot block.");
10318
- }
10319
- else if (actualTechHash !== expectedTechHash) {
10320
- findings.push(`TECH.md architecture snapshot is stale (expected ${expectedTechHash}, found ${actualTechHash}).`);
10942
+ findings.push(`${FOUNDATION_DOCS_DIR}/TECH.md is missing the managed architecture snapshot block.`);
10321
10943
  }
10322
10944
  }
10945
+ if (!adrReadmeExists) {
10946
+ findings.push(`${FOUNDATION_ADR_DIR}/README.md is missing.`);
10947
+ }
10323
10948
  const metadata = await readJsonFileIfExists(metadataPath);
10324
10949
  if (!metadata.exists) {
10325
10950
  findings.push("Architecture build metadata is missing.");
@@ -10327,12 +10952,13 @@ async function readArchitectureDriftStatus(workspaceRoot, snapshot) {
10327
10952
  return {
10328
10953
  stale: findings.length > 0,
10329
10954
  findings,
10330
- rulesPath,
10955
+ productPath,
10956
+ architecturePath,
10331
10957
  techPath,
10958
+ adrReadmePath,
10332
10959
  metadataPath,
10333
- expectedRulesHash,
10334
- expectedTechHash,
10335
- actualRulesHash,
10960
+ actualProductHash,
10961
+ actualArchitectureHash,
10336
10962
  actualTechHash,
10337
10963
  };
10338
10964
  }
@@ -10347,6 +10973,7 @@ async function runBuildArchitecture(options) {
10347
10973
  const cwd = process.cwd();
10348
10974
  const workspaceRoot = findWorkspaceRoot(cwd);
10349
10975
  const snapshot = await collectTechSnapshot(workspaceRoot);
10976
+ const specRoots = await listSpecPackRoots(workspaceRoot);
10350
10977
  if (checkOnly) {
10351
10978
  const drift = await readArchitectureDriftStatus(workspaceRoot, snapshot);
10352
10979
  if (emitJson) {
@@ -10356,6 +10983,7 @@ async function runBuildArchitecture(options) {
10356
10983
  console.log(`Platform: ${platform}`);
10357
10984
  console.log(`Workspace: ${toPosixPath(workspaceRoot)}`);
10358
10985
  console.log(`Status: ${drift.stale ? "stale" : "fresh"}`);
10986
+ console.log(`Backbone docs: ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ${FOUNDATION_DOCS_DIR}/TECH.md, ${FOUNDATION_ADR_DIR}/README.md`);
10359
10987
  if (drift.findings.length > 0) {
10360
10988
  console.log("Findings:");
10361
10989
  for (const finding of drift.findings) {
@@ -10367,13 +10995,13 @@ async function runBuildArchitecture(options) {
10367
10995
  process.exit(1);
10368
10996
  return;
10369
10997
  }
10370
- const scaffold = await ensureArchitectureDocScaffold({
10371
- workspaceRoot,
10372
- snapshot,
10373
- overwrite,
10374
- dryRun,
10375
- });
10376
- const specRoots = await listSpecPackRoots(workspaceRoot);
10998
+ const managedFilePaths = [
10999
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md"),
11000
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "ARCHITECTURE.md"),
11001
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md"),
11002
+ path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md"),
11003
+ path.join(workspaceRoot, FOUNDATION_ADR_DIR, "0000-template.md"),
11004
+ ];
10377
11005
  const coreSkills = [
10378
11006
  "architecture-doc",
10379
11007
  "system-design",
@@ -10383,11 +11011,13 @@ async function runBuildArchitecture(options) {
10383
11011
  const conditionalSkills = resolveArchitectureConditionalSkills(snapshot, specRoots, researchMode);
10384
11012
  const skillBundle = [...coreSkills, ...conditionalSkills];
10385
11013
  const skillPathHints = await resolveArchitectureSkillPathHints(platform, cwd, skillBundle);
11014
+ const inspectionAnchors = await resolveArchitectureInspectionAnchors(workspaceRoot, snapshot, specRoots);
10386
11015
  const prompt = buildArchitecturePrompt({
10387
11016
  platform,
10388
11017
  workspaceRoot,
10389
11018
  snapshot,
10390
11019
  specRoots,
11020
+ inspectionAnchors,
10391
11021
  researchMode,
10392
11022
  coreSkills,
10393
11023
  conditionalSkills,
@@ -10395,6 +11025,13 @@ async function runBuildArchitecture(options) {
10395
11025
  });
10396
11026
  const adapter = await probeArchitectureAdapter(platform, workspaceRoot);
10397
11027
  const args = adapter.buildInvocation(prompt);
11028
+ const managedTargets = [
11029
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "PRODUCT.md"),
11030
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "ARCHITECTURE.md"),
11031
+ path.join(workspaceRoot, FOUNDATION_DOCS_DIR, "TECH.md"),
11032
+ path.join(workspaceRoot, FOUNDATION_ADR_DIR, "README.md"),
11033
+ path.join(workspaceRoot, FOUNDATION_ADR_DIR, "0000-template.md"),
11034
+ ].map((filePath) => toPosixPath(filePath));
10398
11035
  if (dryRun) {
10399
11036
  const summary = {
10400
11037
  platform,
@@ -10402,10 +11039,7 @@ async function runBuildArchitecture(options) {
10402
11039
  adapter: adapter.binary,
10403
11040
  invocation: [adapter.binary, ...args],
10404
11041
  researchMode,
10405
- managedTargets: [
10406
- toPosixPath(scaffold.engineeringRulesPath),
10407
- toPosixPath(scaffold.techMdPath),
10408
- ],
11042
+ managedTargets,
10409
11043
  skillBundle,
10410
11044
  };
10411
11045
  if (emitJson) {
@@ -10416,36 +11050,55 @@ async function runBuildArchitecture(options) {
10416
11050
  console.log(`Workspace: ${toPosixPath(workspaceRoot)}`);
10417
11051
  console.log(`Adapter: ${adapter.binary}`);
10418
11052
  console.log(`Research mode: ${researchMode}`);
10419
- console.log(`Managed targets: ${toPosixPath(scaffold.engineeringRulesPath)}, ${toPosixPath(scaffold.techMdPath)}`);
11053
+ console.log(`Managed targets: ${summary.managedTargets.join(", ")}`);
10420
11054
  console.log(`Skill bundle: ${skillBundle.join(", ")}`);
10421
11055
  console.log(`Invocation: ${[adapter.binary, ...args].join(" ")}`);
10422
11056
  }
10423
11057
  return;
10424
11058
  }
10425
- const execution = await execFileCapture(adapter.binary, args, {
11059
+ const filesBefore = await captureFileContents(managedFilePaths);
11060
+ const scaffold = await ensureArchitectureBuildScaffold({
11061
+ workspaceRoot,
11062
+ dryRun,
11063
+ });
11064
+ if (!emitJson) {
11065
+ console.log(`Streaming ${adapter.binary} output...`);
11066
+ }
11067
+ const execution = await spawnCapture(adapter.binary, args, {
10426
11068
  cwd: workspaceRoot,
10427
11069
  env: process.env,
11070
+ streamOutput: !emitJson,
10428
11071
  });
10429
11072
  if (!execution.ok) {
10430
- throw new Error(`Architecture build failed via ${adapter.binary}. ${String(execution.stderr || execution.stdout || "").trim()}`);
10431
- }
10432
- const rulesContent = await readFile(scaffold.engineeringRulesPath, "utf8");
10433
- const techContent = await readFile(scaffold.techMdPath, "utf8");
11073
+ throw new Error(explainArchitectureBuildFailure(platform, execution));
11074
+ }
11075
+ const filesAfter = await captureFileContents(managedFilePaths);
11076
+ const changedFiles = managedFilePaths
11077
+ .filter((filePath) => filesBefore[filePath] !== filesAfter[filePath])
11078
+ .map((filePath) => toPosixPath(path.relative(workspaceRoot, filePath)));
11079
+ const techContent = filesAfter[scaffold.techMdPath] ?? (await readFile(scaffold.techMdPath, "utf8"));
11080
+ const productContent = filesAfter[scaffold.productPath] ?? (await readFile(scaffold.productPath, "utf8"));
11081
+ const architectureContent = filesAfter[scaffold.architectureDocPath] ??
11082
+ (await readFile(scaffold.architectureDocPath, "utf8"));
10434
11083
  const metadataPath = path.join(workspaceRoot, ".cbx", ARCHITECTURE_BUILD_METADATA_FILENAME);
10435
11084
  const metadata = buildArchitectureBuildMetadata({
10436
11085
  platform,
10437
11086
  researchMode,
10438
- rulesProfileHash: extractTaggedMarkerAttribute(rulesContent, ENGINEERING_ARCHITECTURE_BLOCK_START_RE, "profile") || "unknown",
10439
- techSnapshotHash: extractTaggedMarkerAttribute(techContent, TECH_ARCHITECTURE_BLOCK_START_RE, "snapshot") || "unknown",
11087
+ managedDocs: [
11088
+ `${FOUNDATION_DOCS_DIR}/PRODUCT.md`,
11089
+ `${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md`,
11090
+ `${FOUNDATION_DOCS_DIR}/TECH.md`,
11091
+ `${FOUNDATION_ADR_DIR}/README.md`,
11092
+ `${FOUNDATION_ADR_DIR}/0000-template.md`,
11093
+ ],
10440
11094
  });
10441
11095
  await mkdir(path.dirname(metadataPath), { recursive: true });
10442
11096
  await writeFile(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`, "utf8");
10443
11097
  const result = normalizeArchitectureResult({
10444
11098
  stdout: execution.stdout,
10445
11099
  workspaceRoot: toPosixPath(workspaceRoot),
10446
- rulesPath: "ENGINEERING_RULES.md",
10447
- techPath: "TECH.md",
10448
11100
  researchMode,
11101
+ changedFiles: [...new Set(changedFiles)],
10449
11102
  });
10450
11103
  if (emitJson) {
10451
11104
  console.log(JSON.stringify({
@@ -10459,7 +11112,8 @@ async function runBuildArchitecture(options) {
10459
11112
  console.log(`Platform: ${platform}`);
10460
11113
  console.log(`Adapter: ${adapter.binary}`);
10461
11114
  console.log(`Workspace: ${toPosixPath(workspaceRoot)}`);
10462
- console.log(`Managed docs: ENGINEERING_RULES.md, TECH.md`);
11115
+ console.log(`Managed docs: ${FOUNDATION_DOCS_DIR}/PRODUCT.md, ${FOUNDATION_DOCS_DIR}/ARCHITECTURE.md, ${FOUNDATION_DOCS_DIR}/TECH.md`);
11116
+ console.log(`ADR scaffold: ${FOUNDATION_ADR_DIR}/README.md, ${FOUNDATION_ADR_DIR}/0000-template.md`);
10463
11117
  console.log(`Skill bundle: ${skillBundle.join(", ")}`);
10464
11118
  console.log(`Files written: ${(result.filesWritten || []).join(", ") || "(none reported)"}`);
10465
11119
  console.log(`Research used: ${result.researchUsed ? "yes" : "no"}`);
@@ -10680,10 +11334,7 @@ async function runInitWizard(options) {
10680
11334
  dryRun: installOutcome.dryRun,
10681
11335
  });
10682
11336
  printRuleSyncResult(installOutcome.syncResult);
10683
- printInstallEngineeringSummary({
10684
- engineeringResults: installOutcome.engineeringArtifactsResult.engineeringResults,
10685
- techResult: installOutcome.engineeringArtifactsResult.techResult,
10686
- });
11337
+ printInstallDocumentationNotice();
10687
11338
  printPostmanSetupSummary({
10688
11339
  postmanSetup: installOutcome.postmanSetupResult,
10689
11340
  });