@aifabrix/builder 2.52.1 → 2.53.1

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 (225) hide show
  1. package/lib/app/deploy-config.js +3 -2
  2. package/lib/channels/add-channel.js +11 -41
  3. package/lib/channels/approval-guides/index.js +3 -0
  4. package/lib/channels/approval-guides/microsoft-copilot.js +26 -17
  5. package/lib/channels/channel-add-existing.js +72 -0
  6. package/lib/channels/channel-runtime-resolver.js +5 -1
  7. package/lib/channels/channel-status-display.js +30 -3
  8. package/lib/channels/microsoft-copilot-entra-sso-form.js +73 -2
  9. package/lib/channels/microsoft-copilot-entra-sso.js +26 -5
  10. package/lib/channels/microsoft-copilot-limits.js +22 -3
  11. package/lib/channels/microsoft-copilot-package.js +59 -14
  12. package/lib/channels/microsoft-copilot-validate.js +40 -10
  13. package/lib/cli/attach-default-help-examples.js +102 -0
  14. package/lib/cli/index.js +2 -0
  15. package/lib/cli/setup-credential-deployment.js +7 -5
  16. package/lib/cli/setup-utility-validate.js +1 -0
  17. package/lib/commands/credential-push.js +37 -5
  18. package/lib/commands/package-score.js +72 -0
  19. package/lib/commands/role-assistant.js +46 -8
  20. package/lib/deployment/deployer-poll-run.js +2 -2
  21. package/lib/deployment/deployer.js +1 -1
  22. package/lib/deployment/environment.js +2 -2
  23. package/lib/external-system/deploy.js +11 -21
  24. package/lib/integration-definition/apply.js +12 -14
  25. package/lib/integration-definition/enrich-openapi-operations.js +9 -10
  26. package/lib/lab/package-parity-score.js +417 -0
  27. package/lib/programmatic/capability-registry.js +1 -0
  28. package/lib/programmatic/help-content/channel-onboarding.md +35 -0
  29. package/lib/programmatic/help-content/cip-overview.md +27 -0
  30. package/lib/programmatic/help-content/connected-system-ui.md +70 -0
  31. package/lib/programmatic/help-content/dimensions-guide.md +23 -0
  32. package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
  33. package/lib/programmatic/help-content/overview.md +25 -0
  34. package/lib/programmatic/help-content/subscription-guide.md +27 -0
  35. package/lib/programmatic/help-content/workflow.md +50 -0
  36. package/lib/programmatic/openapi-component-schemas.js +1 -0
  37. package/lib/programmatic/openapi-descriptions.js +6 -0
  38. package/lib/programmatic/openapi-envelope-examples.js +11 -0
  39. package/lib/programmatic/openapi-operation-bindings.js +5 -0
  40. package/lib/programmatic/openapi-request-schemas.js +39 -13
  41. package/lib/programmatic/openapi-result-schemas.js +30 -0
  42. package/lib/programmatic/openapi-schema-descriptions-core.js +18 -0
  43. package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
  44. package/lib/programmatic/persist-supplied-openapi.js +180 -0
  45. package/lib/programmatic/route-handler-map.js +6 -0
  46. package/lib/programmatic/run-integration-definition.js +13 -5
  47. package/lib/role-assistant/evidence-sync.js +55 -7
  48. package/lib/role-assistant/test-runner-attachments.js +118 -0
  49. package/lib/role-assistant/test-runner-bid-apply.js +100 -21
  50. package/lib/role-assistant/test-runner-bid-document.js +1 -1
  51. package/lib/role-assistant/test-runner-start-payload.js +96 -0
  52. package/lib/role-assistant/test-runner-workhub-answers.js +11 -7
  53. package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
  54. package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
  55. package/lib/role-assistant/test-runner-workhub.js +68 -105
  56. package/lib/role-assistant/test-runner.js +5 -63
  57. package/lib/role-assistant/test-suite.js +33 -40
  58. package/lib/schema/external-datasource.schema.json +13 -4
  59. package/lib/utils/compose-generator.js +10 -1
  60. package/lib/utils/compose-traefik-extra-routes.js +107 -0
  61. package/lib/utils/docker-build.js +2 -2
  62. package/lib/utils/help-builder.js +2 -1
  63. package/lib/utils/promote-dev-docker-image.js +15 -10
  64. package/package.json +14 -16
  65. package/templates/README.md +12 -1
  66. package/templates/applications/dataplane/application.yaml +8 -1
  67. package/templates/applications/dataplane/env.template +1 -1
  68. package/templates/applications/miso-controller/application.yaml +2 -1
  69. package/templates/applications/miso-controller/rbac.yaml +1 -0
  70. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +6 -2
  71. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +8 -5
  72. package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
  73. package/templates/channels/microsoft-copilot/install.template.md.hbs +74 -22
  74. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +29 -14
  75. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +6 -2
  76. package/templates/python/docker-compose.hbs +36 -0
  77. package/templates/typescript/docker-compose.hbs +36 -0
  78. package/.cursor/plans/Archive/157.1-security-quality-violations-by-type.csv +0 -374
  79. package/.cursor/process/README.md +0 -9
  80. package/.cursor/rules/anchor-docs.mdc +0 -15
  81. package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
  82. package/.cursor/rules/cli-layout.mdc +0 -81
  83. package/.cursor/rules/cli-product-neutral.mdc +0 -43
  84. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
  85. package/.cursor/rules/docs-rules.mdc +0 -32
  86. package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
  87. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
  88. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
  89. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
  90. package/.cursor/rules/project-rules.mdc +0 -913
  91. package/.cursor/skills/README.md +0 -15
  92. package/.dockerignore +0 -52
  93. package/.eslintignore +0 -22
  94. package/.markdownlint.json +0 -14
  95. package/anchor-docs/README.md +0 -10
  96. package/anchor-docs/_TEMPLATE +0 -24
  97. package/babel.config.js +0 -6
  98. package/bin/builder-api-cleanup.js +0 -26
  99. package/bin/builder-api-nest.js +0 -10
  100. package/bin/builder-api-spike.js +0 -19
  101. package/enterprise-knowledge/README.md +0 -50
  102. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
  103. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
  104. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
  105. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
  106. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
  107. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
  108. package/integration/README.md +0 -81
  109. package/integration/github/README.md +0 -53
  110. package/integration/github/application.json +0 -21
  111. package/integration/github/deploy.js +0 -72
  112. package/integration/github/env.template +0 -11
  113. package/integration/github/github-datasource-issue-comments.json +0 -239
  114. package/integration/github/github-datasource-issues.json +0 -399
  115. package/integration/github/github-datasource-repository.json +0 -354
  116. package/integration/github/github-deploy.json +0 -1202
  117. package/integration/github/github-system.json +0 -82
  118. package/integration/hubspot-test/README.md +0 -159
  119. package/integration/hubspot-test/application.json +0 -54
  120. package/integration/hubspot-test/companies.json +0 -2048
  121. package/integration/hubspot-test/create-hubspot.js +0 -523
  122. package/integration/hubspot-test/env.template +0 -4
  123. package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
  124. package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
  125. package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
  126. package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
  127. package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
  128. package/integration/hubspot-test/hubspot-test-system.json +0 -74
  129. package/integration/hubspot-test/rbac.json +0 -166
  130. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
  131. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
  132. package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
  133. package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
  134. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
  135. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
  136. package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
  137. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
  138. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  139. package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
  140. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
  141. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
  142. package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
  143. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
  144. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  145. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  146. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
  147. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
  148. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
  149. package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
  150. package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
  151. package/integration/hubspot-test/test-dataplane-down.js +0 -209
  152. package/integration/hubspot-test/test.js +0 -1588
  153. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
  154. package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
  155. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
  156. package/integration/roundtrip-test-local/README.md +0 -143
  157. package/integration/roundtrip-test-local/application.yaml +0 -13
  158. package/integration/roundtrip-test-local/env.template +0 -15
  159. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
  160. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
  161. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
  162. package/integration/roundtrip-test-local2/README.md +0 -143
  163. package/integration/roundtrip-test-local2/application.yaml +0 -13
  164. package/integration/roundtrip-test-local2/env.template +0 -15
  165. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
  166. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
  167. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
  168. package/integration/test/wizard.yaml +0 -8
  169. package/jest.config.coverage.js +0 -37
  170. package/jest.config.default.js +0 -11
  171. package/jest.config.integration.fixtures.js +0 -22
  172. package/jest.config.integration.js +0 -33
  173. package/jest.config.isolated.js +0 -11
  174. package/jest.config.manual.js +0 -30
  175. package/jest.global-live-fabrix-hooks.js +0 -36
  176. package/jest.isolated-projects.js +0 -283
  177. package/jest.projects.js +0 -79
  178. package/lib/integration-definition/openapi-enrichment/hubspot-crm-companies.json +0 -205
  179. package/packages/builder-api/README.md +0 -120
  180. package/packages/builder-api/package.json +0 -30
  181. package/packages/builder-api/src/app.module.ts +0 -7
  182. package/packages/builder-api/src/auth/auth.module.ts +0 -5
  183. package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
  184. package/packages/builder-api/src/main.ts +0 -16
  185. package/packages/builder-api/tsconfig.json +0 -15
  186. package/scripts/check-builder-api-architecture-grep.js +0 -79
  187. package/scripts/check-datasource-test-run-schema-sync.js +0 -34
  188. package/scripts/ci-fix.sh +0 -19
  189. package/scripts/ci-simulate.sh +0 -19
  190. package/scripts/diagnose-cli.js +0 -150
  191. package/scripts/docker_image_content_gate.js +0 -47
  192. package/scripts/docker_image_content_gate.sh +0 -5
  193. package/scripts/export-builder-api-evidence.js +0 -262
  194. package/scripts/install-local.js +0 -490
  195. package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
  196. package/scripts/lib/builder-api-docker-staging-core.js +0 -183
  197. package/scripts/lib/docker-image-content-gate-core.js +0 -166
  198. package/scripts/lib/plan-actor.js +0 -109
  199. package/scripts/lib/plan-config.js +0 -20
  200. package/scripts/lib/plan-gates.js +0 -154
  201. package/scripts/lib/plan-meta.js +0 -104
  202. package/scripts/lib/plan-parse.js +0 -162
  203. package/scripts/lib/plan-prevalidate-gates.js +0 -337
  204. package/scripts/lib/plan-run-core.js +0 -125
  205. package/scripts/lib/plan-run-report.js +0 -119
  206. package/scripts/plan-approve.js +0 -24
  207. package/scripts/plan-archive.js +0 -49
  208. package/scripts/plan-run.js +0 -13
  209. package/scripts/plan-set-actor.js +0 -21
  210. package/scripts/plan-validate.js +0 -80
  211. package/scripts/pnpm/af.mjs +0 -125
  212. package/scripts/pnpm/check-quiet.mjs +0 -32
  213. package/scripts/pnpm/dev-install.mjs +0 -29
  214. package/scripts/pnpm/dev-reload.mjs +0 -18
  215. package/scripts/pnpm/help.mjs +0 -55
  216. package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
  217. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
  218. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
  219. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
  220. package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
  221. package/scripts/pnpm/lib/spinner.mjs +0 -42
  222. package/scripts/pnpm-global-remove.js +0 -48
  223. package/scripts/stage_builder_api_for_docker.js +0 -65
  224. package/scripts/sync-builder-api-template.js +0 -44
  225. package/scripts/test-dataplane-bootstrap.js +0 -331
@@ -1,150 +0,0 @@
1
- #!/usr/bin/env node
2
- /* eslint-disable no-console */
3
-
4
- /**
5
- * List every PATH hit for aifabrix / af and each --version (find duplicate installs).
6
- *
7
- * @fileoverview CLI path diagnostic for @aifabrix/builder
8
- */
9
-
10
- const { execFileSync, execSync } = require('child_process');
11
- const fs = require('fs');
12
- const path = require('path');
13
-
14
- /**
15
- * Reads package.json `bin` field.
16
- * @returns {Record<string, string>|string} Bin map or single path string
17
- */
18
- function readBins() {
19
- const pkgPath = path.join(__dirname, '..', 'package.json');
20
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
21
- return pkg.bin || { aifabrix: 'bin/aifabrix.js' };
22
- }
23
-
24
- /**
25
- * Resolves every PATH directory that exposes an executable named `binName`.
26
- * @param {string} binName - CLI name (e.g. aifabrix)
27
- * @returns {Array<{ path: string, real: string }>} Deduped hits with real paths
28
- */
29
- function locationsOnPath(binName) {
30
- if (process.platform === 'win32') {
31
- try {
32
- const out = execSync(`where ${binName}`, {
33
- encoding: 'utf8',
34
- stdio: ['ignore', 'pipe', 'ignore']
35
- }).trim();
36
- return out.split(/\r?\n/).filter(Boolean).map((p) => ({ path: p, real: p }));
37
- } catch {
38
- return [];
39
- }
40
- }
41
-
42
- const dirs = (process.env.PATH || '').split(path.delimiter).filter(Boolean);
43
- const out = [];
44
- const seenReal = new Set();
45
- for (const dir of dirs) {
46
- const candidate = path.join(dir, binName);
47
- try {
48
- const st = fs.lstatSync(candidate);
49
- if (!st.isFile() && !st.isSymbolicLink()) continue;
50
- fs.accessSync(candidate, fs.constants.X_OK);
51
- const real = fs.realpathSync(candidate);
52
- if (seenReal.has(real)) continue;
53
- seenReal.add(real);
54
- out.push({ path: candidate, real });
55
- } catch {
56
- // not found or not executable
57
- }
58
- }
59
- return out;
60
- }
61
-
62
- /**
63
- * Runs `executablePath --version` and returns stdout or null on failure.
64
- * @param {string} executablePath - Absolute path to the binary
65
- * @returns {string|null} Trimmed version output
66
- */
67
- function versionAt(executablePath) {
68
- try {
69
- return execFileSync(executablePath, ['--version'], {
70
- encoding: 'utf8',
71
- stdio: ['ignore', 'pipe', 'ignore']
72
- }).trim();
73
- } catch {
74
- return null;
75
- }
76
- }
77
-
78
- /**
79
- * Prints PNPM_HOME and npm prefix for debugging PATH issues.
80
- * @returns {void}
81
- */
82
- function printEnvironment() {
83
- console.log('Environment (relevant to global CLIs)\n');
84
- console.log(` PNPM_HOME ${process.env.PNPM_HOME || '(not set)'}`);
85
- try {
86
- const prefix = execSync('npm config get prefix', {
87
- encoding: 'utf8',
88
- stdio: ['ignore', 'pipe', 'ignore']
89
- }).trim();
90
- console.log(` npm prefix ${prefix}`);
91
- } catch {
92
- console.log(' npm prefix (could not read)');
93
- }
94
- console.log('');
95
- }
96
-
97
- /**
98
- * @param {string[]} names - Bin names from package.json
99
- * @returns {void}
100
- */
101
- function printBinReports(names) {
102
- for (const name of names) {
103
- console.log(`── ${name} ──`);
104
- const hits = locationsOnPath(name);
105
- if (!hits.length) {
106
- console.log(' (not found on PATH)\n');
107
- continue;
108
- }
109
- hits.forEach((h, i) => {
110
- const ver = versionAt(h.path);
111
- const marker = i === 0 ? ' ← first on PATH (what your shell runs)' : '';
112
- console.log(` [${i + 1}] ${h.path}`);
113
- if (h.real !== h.path) console.log(` → ${h.real}`);
114
- console.log(` --version: ${ver ?? '(failed to run)'}${marker}`);
115
- });
116
- console.log('');
117
- }
118
- }
119
-
120
- /**
121
- * @param {string[]} names - Bin names from package.json
122
- * @returns {void}
123
- */
124
- function warnIfMultipleVersions(names) {
125
- const uniqVersions = new Set();
126
- for (const name of names) {
127
- for (const h of locationsOnPath(name)) {
128
- const v = versionAt(h.path);
129
- if (v) uniqVersions.add(v);
130
- }
131
- }
132
- if (uniqVersions.size > 1) {
133
- console.log('⚠ Multiple distinct --version values above: remove or reorder PATH so only one install remains.');
134
- console.log(' Often: npm uninstall -g @aifabrix/builder, then ensure PNPM_HOME is before /usr/local/bin in PATH.\n');
135
- }
136
- }
137
-
138
- /**
139
- * Entry: list PATH hits and versions for each package bin.
140
- * @returns {void}
141
- */
142
- function main() {
143
- const binField = readBins();
144
- const names = typeof binField === 'string' ? ['aifabrix'] : Object.keys(binField);
145
- printEnvironment();
146
- printBinReports(names);
147
- warnIfMultipleVersions(names);
148
- }
149
-
150
- main();
@@ -1,47 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Fail when a built Docker image contains dev-only paths (plan 154.3).
4
- *
5
- * @fileoverview builder-api image content gate
6
- * @author AI Fabrix Team
7
- * @version 1.0.0
8
- */
9
-
10
- 'use strict';
11
-
12
- const { checkImage } = require('./lib/docker-image-content-gate-core');
13
-
14
- /**
15
- * @param {string[]} argv
16
- * @returns {number}
17
- */
18
- function main(argv) {
19
- const args = argv.slice(2);
20
- if (args.length < 2) {
21
- console.error('Usage: docker_image_content_gate.js <image> <profile>');
22
- return 1;
23
- }
24
-
25
- const [image, profile] = args;
26
- try {
27
- const violations = checkImage(image, profile);
28
- if (violations.length > 0) {
29
- console.error(`Image ${image} failed ${profile} content gate:`);
30
- for (const path of violations) {
31
- console.error(` - forbidden: ${path}`);
32
- }
33
- return 1;
34
- }
35
- console.log(`OK: ${image} passed ${profile} content gate`);
36
- return 0;
37
- } catch (error) {
38
- console.error(`ERROR: ${error.message}`);
39
- return 1;
40
- }
41
- }
42
-
43
- if (require.main === module) {
44
- process.exit(main(process.argv));
45
- }
46
-
47
- module.exports = { main };
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env sh
2
- # Plan 154.3 — verify a built builder-api image does not contain dev-only trees.
3
- set -eu
4
- ROOT="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
5
- exec node "$ROOT/scripts/docker_image_content_gate.js" "$@"
@@ -1,262 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Export builder-api help/knowledge fixtures to Evidence Fabrix v2 bulk-load JSON.
4
- *
5
- * @fileoverview One-time / repeatable generator for Role Assistant evidence import
6
- * @author AI Fabrix Team
7
- * @version 1.0.0
8
- */
9
-
10
- 'use strict';
11
-
12
- const fs = require('fs');
13
- const path = require('path');
14
-
15
- const REPO_ROOT = path.join(__dirname, '..');
16
- const DEFAULT_OUT = path.join(
17
- REPO_ROOT,
18
- '..',
19
- 'aifabrix-dataplane',
20
- 'integration',
21
- 'builder-api',
22
- 'builder-api-evidence.json'
23
- );
24
-
25
- const EVIDENCE_PATTERNS = path.join(REPO_ROOT, 'docs', 'builder-help', 'evidence-patterns.json');
26
- const GOLDEN_DIR = path.join(REPO_ROOT, 'docs', 'builder-help', 'golden-examples');
27
- const PLATFORM_ROLES = path.join(REPO_ROOT, 'docs', 'builder-help', 'platform-roles.json');
28
- const RESOURCE_CATALOG = path.join(REPO_ROOT, 'docs', 'builder-help', 'resource-type-catalog.json');
29
- const HELP_MD_DIR = path.join(REPO_ROOT, 'lib', 'programmatic', 'help-content');
30
-
31
- /** @type {Array<{ file: string, resourceType: string, order: number }>} */
32
- const MD_TOPICS = [
33
- { file: 'overview.md', resourceType: 'workspace', order: 10 },
34
- { file: 'workflow.md', resourceType: 'workspace', order: 20 },
35
- { file: 'subscription-guide.md', resourceType: 'system', order: 30 },
36
- { file: 'cip-overview.md', resourceType: 'task', order: 40 },
37
- { file: 'dimensions-guide.md', resourceType: 'policy', order: 50 },
38
- { file: 'channel-onboarding.md', resourceType: 'channel', order: 60 },
39
- { file: 'connected-system-ui.md', resourceType: 'workspace', order: 70 }
40
- ];
41
-
42
- /**
43
- * @param {string} text
44
- * @returns {string}
45
- */
46
- function stripMarkdown(text) {
47
- return String(text || '')
48
- .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
49
- .replace(/https?:\/\/[^\s)]+/gi, '')
50
- .replace(/^#+\s*/gm, '')
51
- .replace(/\s{2,}/g, ' ')
52
- .trim();
53
- }
54
-
55
- /**
56
- * @param {string} fileName
57
- * @returns {{ title: string, summary: string, body: string }}
58
- */
59
- function parseMarkdownTopic(fileName) {
60
- const raw = fs.readFileSync(path.join(HELP_MD_DIR, fileName), 'utf8');
61
- const lines = raw.split(/\r?\n/);
62
- let title = path.basename(fileName, '.md');
63
- const bodyLines = [];
64
- for (const line of lines) {
65
- if (line.startsWith('# ')) {
66
- title = stripMarkdown(line.slice(2));
67
- } else if (line.trim()) {
68
- bodyLines.push(line);
69
- }
70
- }
71
- const body = stripMarkdown(bodyLines.join('\n'));
72
- const summary = body.slice(0, 240);
73
- return { title, summary, body };
74
- }
75
-
76
- /**
77
- * @param {Object} row
78
- * @returns {Object}
79
- */
80
- function normalizeRow(row) {
81
- const out = {
82
- resourceType: String(row.resourceType || 'workspace').trim(),
83
- title: String(row.title || '').trim(),
84
- when: String(row.when || '').trim(),
85
- expectedBehavior: String(row.expectedBehavior || '').trim(),
86
- order: Number.isFinite(row.order) ? row.order : 100,
87
- status: row.status === 'disabled' ? 'disabled' : 'active'
88
- };
89
- if (row.roleKey) {
90
- out.roleKey = String(row.roleKey).trim();
91
- }
92
- if (row.description) {
93
- out.description = String(row.description).trim();
94
- }
95
- return out;
96
- }
97
-
98
- /**
99
- * @returns {Object[]}
100
- */
101
- function rowsFromEvidencePatterns() {
102
- const doc = JSON.parse(fs.readFileSync(EVIDENCE_PATTERNS, 'utf8'));
103
- return (doc.patterns || []).map((p, i) =>
104
- normalizeRow({
105
- resourceType: p.resourceType || 'document',
106
- title: p.title,
107
- description: [p.summary, p.role ? `Audience: ${p.role}` : null, (p.steps || []).join(' → ')].filter(Boolean).join(' '),
108
- when: p.summary || p.title,
109
- expectedBehavior: (p.steps || []).join(' '),
110
- order: 100 + i
111
- })
112
- );
113
- }
114
-
115
- /**
116
- * @returns {Object[]}
117
- */
118
- function rowsFromGoldenExamples() {
119
- const rows = [];
120
- let order = 200;
121
- for (const file of fs.readdirSync(GOLDEN_DIR).sort()) {
122
- if (!file.endsWith('.json')) {
123
- continue;
124
- }
125
- const doc = JSON.parse(fs.readFileSync(path.join(GOLDEN_DIR, file), 'utf8'));
126
- const traversal = (doc.metadataTraversal || []).join(', ');
127
- rows.push(
128
- normalizeRow({
129
- resourceType: doc.resourceType || 'document',
130
- title: `Golden example: ${doc.title || doc.key}`,
131
- description: [doc.summary, doc.role ? `Audience: ${doc.role}` : null].filter(Boolean).join(' '),
132
- when: `Designing a ${doc.resourceType || 'document'} integration similar to ${doc.key}`,
133
- expectedBehavior: [
134
- doc.summary,
135
- doc.subscriptionGuidance,
136
- traversal ? `Traverse sections: ${traversal}` : null,
137
- (doc.recommendedSectionKeys || []).length
138
- ? `Recommended sections: ${doc.recommendedSectionKeys.join(', ')}`
139
- : null
140
- ]
141
- .filter(Boolean)
142
- .join(' '),
143
- order: order++
144
- })
145
- );
146
- }
147
- return rows;
148
- }
149
-
150
- /**
151
- * @returns {Object[]}
152
- */
153
- function rowsFromMarkdownTopics() {
154
- return MD_TOPICS.map((t) => {
155
- const parsed = parseMarkdownTopic(t.file);
156
- return normalizeRow({
157
- resourceType: t.resourceType,
158
- title: parsed.title,
159
- description: parsed.summary,
160
- when: `Agent needs builder-api guidance for ${parsed.title}`,
161
- expectedBehavior: parsed.body,
162
- order: t.order
163
- });
164
- });
165
- }
166
-
167
- /**
168
- * @returns {Object[]}
169
- */
170
- function rowsFromPlatformRoles() {
171
- const doc = JSON.parse(fs.readFileSync(PLATFORM_ROLES, 'utf8'));
172
- const roleLines = (doc.roles || [])
173
- .map((r) => `${r.value}: ${r.description}`)
174
- .join(' ');
175
- return [
176
- normalizeRow({
177
- resourceType: 'policy',
178
- title: 'Platform RBAC roles for facade integrations',
179
- description: 'Dataplane platform roles for orchestration facade systems (not per-system admin/reader).',
180
- when: 'Patching system.rolesPermissions or repair rbac on a builder-api facade system',
181
- expectedBehavior: `Use rbacPreset platform. Allowed roles: ${roleLines}. Avoid {systemKey}-admin or {systemKey}-reader on facade APIs.`,
182
- order: 5
183
- })
184
- ];
185
- }
186
-
187
- /**
188
- * @returns {Object[]}
189
- */
190
- function rowsFromResourceCatalog() {
191
- const doc = JSON.parse(fs.readFileSync(RESOURCE_CATALOG, 'utf8'));
192
- const byCategory = {};
193
- for (const rt of doc.resourceTypes || []) {
194
- const cat = rt.category || 'other';
195
- if (!byCategory[cat]) {
196
- byCategory[cat] = [];
197
- }
198
- byCategory[cat].push(`${rt.key} (${rt.description})`);
199
- }
200
- const summary = Object.entries(byCategory)
201
- .map(([cat, items]) => `${cat}: ${items.slice(0, 8).join('; ')}`)
202
- .join(' ');
203
- return [
204
- normalizeRow({
205
- resourceType: 'document',
206
- title: 'Resource type catalog for datasource manifests',
207
- description: 'Pick catalog keys that match business semantics; challenge generic placeholders.',
208
- when: 'Choosing datasource.resourceType for a new or edited datasource',
209
- expectedBehavior: `Compare purpose to catalog entries. Minimum system keys: ${(doc.minimumSystemKeys || []).join(', ')}. Categories: ${summary}`,
210
- order: 8
211
- })
212
- ];
213
- }
214
-
215
- /**
216
- * @returns {Object[]}
217
- */
218
- function rowsFromManifestGuides() {
219
- return [
220
- normalizeRow({
221
- resourceType: 'policy',
222
- title: 'Manifest section keys and dependency order',
223
- when: 'Agent edits external system or datasource manifest sections',
224
- expectedBehavior:
225
- 'Read one section at a time via manifest section APIs. After metadata or capability patches, run repair hooks for fieldMappings, expose, and rbac. Use dependency graph: downstream sections derive from upstream patches.',
226
- order: 15
227
- }),
228
- normalizeRow({
229
- resourceType: 'workspace',
230
- title: 'Repair hooks and CLI flag mapping',
231
- when: 'Manifest repair is required after structural edits',
232
- expectedBehavior:
233
- 'POST manifest repair with explicit hooks (fieldMappings, expose, rbac, sync, test). Align with repair CLI flags. Validate workspace before upload or certify.',
234
- order: 16
235
- }),
236
- normalizeRow({
237
- resourceType: 'workspace',
238
- title: 'Section quality and missing inputs',
239
- when: 'GET manifest section returns quality.missingInputs',
240
- expectedBehavior:
241
- 'Collect required missing inputs from the user before PATCH. Do not guess values. sectionReadToken from GET is optional on PATCH (server re-reads when omitted; stale token returns 409). Prefer GET when you need quality or missingInputs.',
242
- order: 17
243
- })
244
- ];
245
- }
246
-
247
- function main() {
248
- const outPath = path.resolve(process.argv[2] || DEFAULT_OUT);
249
- const rows = [
250
- ...rowsFromPlatformRoles(),
251
- ...rowsFromResourceCatalog(),
252
- ...rowsFromMarkdownTopics(),
253
- ...rowsFromManifestGuides(),
254
- ...rowsFromEvidencePatterns(),
255
- ...rowsFromGoldenExamples()
256
- ];
257
- fs.mkdirSync(path.dirname(outPath), { recursive: true });
258
- fs.writeFileSync(outPath, `${JSON.stringify(rows, null, 2)}\n`, 'utf8');
259
- process.stdout.write(`Wrote ${rows.length} evidence row(s) to ${outPath}\n`);
260
- }
261
-
262
- main();