@aifabrix/builder 2.51.0 → 2.51.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 (162) hide show
  1. package/jest.isolated-projects.js +77 -1
  2. package/jest.projects.js +5 -426
  3. package/lib/api/assistants.api.js +67 -0
  4. package/lib/api/datasources-extended.api.js +6 -6
  5. package/lib/api/evidence-authoring-helpers.js +267 -0
  6. package/lib/api/evidence-authoring.api.js +337 -0
  7. package/lib/api/evidence.api.js +57 -1
  8. package/lib/api/index.js +24 -7
  9. package/lib/api/pipeline.api.js +43 -3
  10. package/lib/api/records-bulk.api.js +28 -3
  11. package/lib/api/types/evidence.types.js +156 -8
  12. package/lib/api/work.api.js +283 -0
  13. package/lib/app/run-deploy-job.js +108 -0
  14. package/lib/app/run-helpers.js +10 -3
  15. package/lib/app/run.js +8 -0
  16. package/lib/channels/add-channel.js +54 -23
  17. package/lib/channels/approval-guides/chatgpt.js +8 -7
  18. package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
  19. package/lib/channels/channel-artifact-generator.js +14 -2
  20. package/lib/channels/channel-credential.js +3 -1
  21. package/lib/channels/channel-probe-evidence.js +79 -0
  22. package/lib/channels/channel-probe.js +265 -13
  23. package/lib/channels/channel-runtime-resolver.js +120 -29
  24. package/lib/channels/channel-status-display.js +44 -0
  25. package/lib/channels/channel-targets.js +7 -0
  26. package/lib/channels/chatgpt-runtime-contract.js +29 -0
  27. package/lib/channels/microsoft-copilot-package.js +280 -0
  28. package/lib/channels/runtime-tool-catalog.js +165 -0
  29. package/lib/cli/index.js +2 -0
  30. package/lib/cli/setup-app.js +4 -0
  31. package/lib/cli/setup-external-system-help.js +8 -2
  32. package/lib/cli/setup-external-system.js +12 -0
  33. package/lib/commands/app-test.js +2 -14
  34. package/lib/commands/datasource-load-export-cli.js +6 -1
  35. package/lib/commands/deploy-gate-failure-details.js +19 -17
  36. package/lib/commands/dev-down.js +2 -6
  37. package/lib/commands/evidence-kind.js +65 -15
  38. package/lib/commands/governance-generate-external.js +56 -21
  39. package/lib/commands/lifecycle-external.js +10 -4
  40. package/lib/commands/repair-datasource-apply.js +10 -1
  41. package/lib/commands/repair-datasource-run.js +4 -2
  42. package/lib/commands/repair-datasource-test-payload.js +80 -19
  43. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
  44. package/lib/commands/repair-internal.js +9 -1
  45. package/lib/commands/repair-openapi-sync.js +34 -17
  46. package/lib/commands/role-assistant.js +313 -0
  47. package/lib/commands/upload-data-sync-finalize.js +5 -4
  48. package/lib/commands/upload-sidecar-followups.js +144 -47
  49. package/lib/commands/upload.js +43 -6
  50. package/lib/commands/verify-governance-combined-external.js +73 -9
  51. package/lib/commands/verify-governance-db.js +80 -25
  52. package/lib/commands/verify-governance-external.js +29 -5
  53. package/lib/commands/wizard-core-helpers.js +7 -3
  54. package/lib/commands/wizard-core.js +78 -9
  55. package/lib/datasource/bulk-loader-run-batches.js +4 -2
  56. package/lib/datasource/bulk-loader-service.js +5 -1
  57. package/lib/datasource/datasource-validate-summary.js +2 -2
  58. package/lib/datasource/validate.js +13 -6
  59. package/lib/external-system/deploy-helpers.js +35 -1
  60. package/lib/external-system/deploy.js +23 -10
  61. package/lib/external-system/download-helpers.js +111 -2
  62. package/lib/external-system/download-role-assistant.js +55 -0
  63. package/lib/external-system/download.js +45 -26
  64. package/lib/external-system/test-helpers.js +1 -1
  65. package/lib/external-system/test.js +39 -3
  66. package/lib/generator/builders.js +3 -0
  67. package/lib/generator/wizard.js +51 -4
  68. package/lib/lifecycle/access-control-abac.js +121 -0
  69. package/lib/lifecycle/lifecycle-governance-options.js +4 -1
  70. package/lib/lifecycle/product-model.js +3 -2
  71. package/lib/lifecycle/report-display.js +14 -2
  72. package/lib/programmatic/capability-registry.js +20 -1
  73. package/lib/programmatic/command-options.js +1 -0
  74. package/lib/programmatic/index.js +4 -0
  75. package/lib/programmatic/manifest-patch-section.js +48 -9
  76. package/lib/programmatic/manifest-section-registry-data.js +3 -2
  77. package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
  78. package/lib/programmatic/openapi-component-schemas.js +16 -1
  79. package/lib/programmatic/openapi-description-enricher.js +3 -1
  80. package/lib/programmatic/openapi-descriptions.js +55 -5
  81. package/lib/programmatic/openapi-evidence-schemas.js +161 -0
  82. package/lib/programmatic/openapi-manifest-schemas.js +6 -2
  83. package/lib/programmatic/openapi-operation-bindings.js +99 -0
  84. package/lib/programmatic/openapi-request-schemas.js +36 -1
  85. package/lib/programmatic/openapi-result-schemas.js +1 -1
  86. package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
  87. package/lib/programmatic/openapi-schema-descriptions-core.js +1 -1
  88. package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
  89. package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
  90. package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
  91. package/lib/programmatic/openapi-spec.js +47 -28
  92. package/lib/programmatic/orchestration-openapi-meta.js +5 -0
  93. package/lib/programmatic/request-timeout.js +3 -0
  94. package/lib/programmatic/route-handler-map.js +89 -2
  95. package/lib/programmatic/run-certify.js +15 -2
  96. package/lib/programmatic/run-deploy.js +74 -0
  97. package/lib/programmatic/run-evidence-authoring.js +80 -0
  98. package/lib/programmatic/run-protection.js +124 -0
  99. package/lib/programmatic/run-template-workspace.js +28 -1
  100. package/lib/programmatic/workspace-context.js +6 -0
  101. package/lib/protection/auth-context.js +48 -6
  102. package/lib/protection/paths.js +22 -0
  103. package/lib/protection/run-protection-create-helpers.js +22 -1
  104. package/lib/protection/run-protection-create.js +1 -1
  105. package/lib/protection/sync-after-upload.js +1 -1
  106. package/lib/role-assistant/evidence-sync.js +450 -0
  107. package/lib/role-assistant/github-workflow.js +96 -0
  108. package/lib/role-assistant/knowledge-sync.js +465 -0
  109. package/lib/role-assistant/settings.js +126 -0
  110. package/lib/role-assistant/test-cases-evaluate.js +170 -0
  111. package/lib/role-assistant/test-cases-honesty.js +184 -0
  112. package/lib/role-assistant/test-cases.js +364 -0
  113. package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
  114. package/lib/role-assistant/test-runner-workhub.js +385 -0
  115. package/lib/role-assistant/test-runner.js +500 -0
  116. package/lib/schema/application-schema.json +16 -2
  117. package/lib/schema/deployment-rules.yaml +1 -0
  118. package/lib/schema/external-datasource.schema.json +38 -4
  119. package/lib/schema/external-system.schema.json +4 -4
  120. package/lib/schema/infra.parameter.yaml +20 -0
  121. package/lib/schema/role-assistant-settings.schema.json +108 -0
  122. package/lib/utils/api.js +52 -27
  123. package/lib/utils/app-path-resolve.js +72 -24
  124. package/lib/utils/authentication-shape.js +3 -1
  125. package/lib/utils/deployment-validation.js +28 -3
  126. package/lib/utils/docker-run-ephemeral.js +55 -0
  127. package/lib/utils/enterprise-knowledge-paths.js +29 -12
  128. package/lib/utils/env-copy-keycloak.js +196 -0
  129. package/lib/utils/env-copy.js +34 -1
  130. package/lib/utils/external-system-readiness-compact-display.js +3 -0
  131. package/lib/utils/help-builder.js +1 -0
  132. package/lib/utils/paths.js +67 -23
  133. package/lib/utils/pipeline-upload-auth-retry.js +15 -3
  134. package/lib/utils/role-assistant-paths.js +98 -0
  135. package/lib/utils/schema-loader.js +41 -0
  136. package/lib/utils/schema-resolver.js +36 -4
  137. package/lib/utils/token-manager.js +38 -29
  138. package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
  139. package/lib/validation/external-manifest-validator.js +31 -8
  140. package/lib/validation/validate-external-file.js +8 -1
  141. package/package.json +2 -1
  142. package/scripts/export-builder-api-evidence.js +1 -1
  143. package/templates/applications/dataplane/application.yaml +23 -15
  144. package/templates/applications/dataplane/env.template +1 -1
  145. package/templates/applications/dataplane/rbac.yaml +14 -0
  146. package/templates/applications/miso-controller/application.yaml +1 -1
  147. package/templates/applications/miso-controller/env.template +3 -1
  148. package/templates/channels/chatgpt/install.template.md.hbs +42 -24
  149. package/templates/channels/chatgpt/integration/README.md +10 -7
  150. package/templates/channels/chatgpt/integration/application.json +2 -2
  151. package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
  152. package/templates/channels/chatgpt/integration/env.template +1 -1
  153. package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
  154. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
  155. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
  156. package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
  157. package/templates/channels/microsoft-copilot/integration/README.md +9 -7
  158. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  159. package/templates/channels/microsoft-copilot/integration/env.template +1 -1
  160. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
  161. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
  162. /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Role assistant test-case expectation evaluation.
3
+ * @fileoverview Evaluate lifecycle/capability/fact/honesty expectations for a case result
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const {
9
+ buildHonestyObservation,
10
+ evaluateHonestyExpectations
11
+ } = require('./test-cases-honesty');
12
+
13
+ function getValueAtPath(obj, dottedPath) {
14
+ const parts = String(dottedPath || '').split('.').filter(Boolean);
15
+ let cursor = obj;
16
+ for (const key of parts) {
17
+ if (!cursor || typeof cursor !== 'object' || !(key in cursor)) {
18
+ return undefined;
19
+ }
20
+ cursor = cursor[key];
21
+ }
22
+ return cursor;
23
+ }
24
+
25
+ function evaluateLifecycleStateExpectation(expectedState, observedState) {
26
+ if (!expectedState) {
27
+ return null;
28
+ }
29
+ const expected = String(expectedState).trim();
30
+ const passed = expected === observedState;
31
+ return {
32
+ id: 'expected.lifecycleState',
33
+ passed,
34
+ message: passed
35
+ ? `Lifecycle state matched expected value "${expected}".`
36
+ : `Lifecycle state expected "${expected}" but got "${observedState}".`
37
+ };
38
+ }
39
+
40
+ function evaluateCapabilityExpectations(requiredList, observedCapabilities) {
41
+ if (!Array.isArray(requiredList) || requiredList.length === 0) {
42
+ return [];
43
+ }
44
+ const observedSet = new Set(observedCapabilities);
45
+ return requiredList.map((capability) => {
46
+ const key = String(capability || '').trim();
47
+ const passed = observedSet.has(key);
48
+ return {
49
+ id: `expected.capabilities.required:${key}`,
50
+ passed,
51
+ message: passed
52
+ ? `Required capability "${key}" observed.`
53
+ : `Required capability "${key}" was not observed.`
54
+ };
55
+ });
56
+ }
57
+
58
+ function evaluateFactExpectations(expectedFacts, observation) {
59
+ if (!expectedFacts || typeof expectedFacts !== 'object' || Array.isArray(expectedFacts)) {
60
+ return [];
61
+ }
62
+ return Object.entries(expectedFacts).map(([factPath, expectedValue]) => {
63
+ const actualValue = getValueAtPath(observation, factPath);
64
+ const passed = JSON.stringify(actualValue) === JSON.stringify(expectedValue);
65
+ return {
66
+ id: `expected.facts:${factPath}`,
67
+ passed,
68
+ message: passed
69
+ ? `Fact "${factPath}" matched expected value.`
70
+ : `Fact "${factPath}" expected ${JSON.stringify(expectedValue)} but got ${JSON.stringify(actualValue)}.`
71
+ };
72
+ });
73
+ }
74
+
75
+ function evaluateProhibitedExpectations(prohibited, observation) {
76
+ if (!Array.isArray(prohibited) || prohibited.length === 0) {
77
+ return [];
78
+ }
79
+ return prohibited.map((factPath) => {
80
+ const actualValue = getValueAtPath(observation, factPath);
81
+ const passed = actualValue === undefined || actualValue === null || actualValue === false;
82
+ return {
83
+ id: `expected.prohibited:${factPath}`,
84
+ passed,
85
+ message: passed
86
+ ? `Prohibited marker "${factPath}" was not observed.`
87
+ : `Prohibited marker "${factPath}" observed: ${JSON.stringify(actualValue)}.`
88
+ };
89
+ });
90
+ }
91
+
92
+ function buildCaseObservation(result, lifecycleVerdict, portalUrl) {
93
+ const {
94
+ deriveLifecycleState,
95
+ collectObservedCapabilities
96
+ } = require('./test-cases');
97
+ const observedState = deriveLifecycleState(result, lifecycleVerdict);
98
+ const observedCapabilities = collectObservedCapabilities(result);
99
+ const workResult =
100
+ result?.workResult && typeof result.workResult === 'object' ? result.workResult : null;
101
+ return {
102
+ lifecycleState: observedState,
103
+ verdict: lifecycleVerdict,
104
+ openApiPublished: result?.openApiPublished === true,
105
+ portalUrl,
106
+ report: result?.report || {},
107
+ stepsRun: Array.isArray(result?.stepsRun) ? result.stepsRun : [],
108
+ capabilities: { observed: observedCapabilities },
109
+ processExecutionId: result?.processExecutionId || null,
110
+ workResult,
111
+ workResultError: result?.workResultError || null,
112
+ honesty: buildHonestyObservation(workResult)
113
+ };
114
+ }
115
+
116
+ function softWrapLifecycleAssertion(lifecycleAssertion, soft) {
117
+ if (!lifecycleAssertion) {
118
+ return null;
119
+ }
120
+ if (!(soft && !lifecycleAssertion.passed)) {
121
+ return lifecycleAssertion;
122
+ }
123
+ return {
124
+ ...lifecycleAssertion,
125
+ passed: true,
126
+ soft: true,
127
+ warn: true,
128
+ message: `${lifecycleAssertion.message} (soft — warning only)`
129
+ };
130
+ }
131
+
132
+ function collectCaseAssertions(expected, observation) {
133
+ const soft = expected.soft === true;
134
+ const observedCapabilities = observation.capabilities?.observed || [];
135
+ const assertions = [];
136
+ const lifecycleAssertion = softWrapLifecycleAssertion(
137
+ evaluateLifecycleStateExpectation(expected.lifecycleState, observation.lifecycleState),
138
+ soft
139
+ );
140
+ if (lifecycleAssertion) {
141
+ assertions.push(lifecycleAssertion);
142
+ }
143
+ assertions.push(
144
+ ...evaluateCapabilityExpectations(expected?.capabilities?.required, observedCapabilities)
145
+ );
146
+ assertions.push(...evaluateFactExpectations(expected.facts, observation));
147
+ assertions.push(...evaluateProhibitedExpectations(expected.prohibited, observation));
148
+ assertions.push(...evaluateHonestyExpectations(expected.honesty, observation, { soft }));
149
+ return assertions;
150
+ }
151
+
152
+ function evaluateRoleAssistantTestCase(testCase, result, lifecycleVerdict, portalUrl) {
153
+ const observation = buildCaseObservation(result, lifecycleVerdict, portalUrl);
154
+ const assertions = collectCaseAssertions(testCase.expected || {}, observation);
155
+ const failed = assertions.filter((row) => !row.passed);
156
+ return {
157
+ caseId: testCase.caseId,
158
+ sourceFile: testCase.sourceFile,
159
+ passed: failed.length === 0,
160
+ lifecycleState: observation.lifecycleState,
161
+ assertions,
162
+ failedAssertions: failed,
163
+ warnings: assertions.filter((row) => row.warn === true),
164
+ observation
165
+ };
166
+ }
167
+
168
+ module.exports = {
169
+ evaluateRoleAssistantTestCase
170
+ };
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Soft / structural honesty assertions for role-assistant test cases.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const HONESTY_COMPLETION_STATES = new Set([
8
+ 'notEvaluated',
9
+ 'waiting',
10
+ 'completed',
11
+ 'failed',
12
+ 'cancelled',
13
+ 'safeStopped'
14
+ ]);
15
+ const HONESTY_GOAL_STATUSES = new Set([
16
+ 'unverified',
17
+ 'partiallySatisfied',
18
+ 'satisfied',
19
+ 'notSatisfied'
20
+ ]);
21
+ const HONESTY_CONTRIB_STATUSES = new Set([
22
+ 'notDefined',
23
+ 'expected',
24
+ 'pendingVerification',
25
+ 'realized',
26
+ 'notRealized',
27
+ 'partial'
28
+ ]);
29
+
30
+ function emptyHonestyObservation() {
31
+ return {
32
+ present: false,
33
+ schemaVersion: null,
34
+ effectiveDepth: null,
35
+ completionState: null,
36
+ goalStatus: null,
37
+ contributionStatus: null,
38
+ resourceChangeCount: 0,
39
+ relationshipChangeCount: 0
40
+ };
41
+ }
42
+
43
+ function asObject(value) {
44
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
45
+ }
46
+
47
+ function buildHonestyObservation(workResult) {
48
+ if (!workResult || typeof workResult !== 'object') {
49
+ return emptyHonestyObservation();
50
+ }
51
+ const completion = asObject(workResult.completion);
52
+ const measurements = asObject(workResult.measurements);
53
+ const contribution = asObject(measurements.contributionObservation);
54
+ const businessChanges = asObject(workResult.businessChanges);
55
+ const resources = Array.isArray(businessChanges.resources) ? businessChanges.resources : [];
56
+ const relationships = Array.isArray(businessChanges.relationships)
57
+ ? businessChanges.relationships
58
+ : [];
59
+ return {
60
+ present: true,
61
+ schemaVersion: workResult.schemaVersion || null,
62
+ effectiveDepth: workResult.effectiveDepth || null,
63
+ completionState: completion.state || null,
64
+ goalStatus: completion.goalStatus || null,
65
+ contributionStatus: contribution.status || null,
66
+ resourceChangeCount: resources.length,
67
+ relationshipChangeCount: relationships.length
68
+ };
69
+ }
70
+
71
+ function pushHonestyAssertion(assertions, id, passed, message) {
72
+ assertions.push({ id, passed, message });
73
+ }
74
+
75
+ function assertWorkResultPresent(assertions, honesty, observation) {
76
+ const present = honesty.present === true;
77
+ const missingSuffix = observation.workResultError
78
+ ? `: ${observation.workResultError}`
79
+ : '.';
80
+ pushHonestyAssertion(
81
+ assertions,
82
+ 'expected.honesty.requireWorkResult',
83
+ present,
84
+ present
85
+ ? 'work.result Output was present.'
86
+ : `work.result Output missing${missingSuffix}`
87
+ );
88
+ }
89
+
90
+ function assertSchemaVersion(assertions, honestySpec, honesty) {
91
+ if (!honestySpec.schemaVersion) {
92
+ return;
93
+ }
94
+ const expected = String(honestySpec.schemaVersion);
95
+ const passed = String(honesty.schemaVersion || '') === expected;
96
+ pushHonestyAssertion(
97
+ assertions,
98
+ 'expected.honesty.schemaVersion',
99
+ passed,
100
+ passed
101
+ ? `schemaVersion matched "${expected}".`
102
+ : `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}.`
103
+ );
104
+ }
105
+
106
+ function assertCompletion(assertions, honestySpec, honesty) {
107
+ if (honestySpec.requireCompletion === false) {
108
+ return;
109
+ }
110
+ const stateOk = HONESTY_COMPLETION_STATES.has(String(honesty.completionState || ''));
111
+ const goalOk = HONESTY_GOAL_STATUSES.has(String(honesty.goalStatus || ''));
112
+ pushHonestyAssertion(
113
+ assertions,
114
+ 'expected.honesty.completion',
115
+ stateOk && goalOk,
116
+ stateOk && goalOk
117
+ ? `completion.state/goalStatus honest (${honesty.completionState}/${honesty.goalStatus}).`
118
+ : `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}.`
119
+ );
120
+ }
121
+
122
+ function assertContribution(assertions, honestySpec, honesty) {
123
+ if (honestySpec.requireContributionObservation === false) {
124
+ return;
125
+ }
126
+ const ok = HONESTY_CONTRIB_STATUSES.has(String(honesty.contributionStatus || ''));
127
+ pushHonestyAssertion(
128
+ assertions,
129
+ 'expected.honesty.contributionObservation',
130
+ ok,
131
+ ok
132
+ ? `contributionObservation.status honest (${honesty.contributionStatus}).`
133
+ : `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}.`
134
+ );
135
+ }
136
+
137
+ function assertMinResourceChanges(assertions, honestySpec, honesty, soft) {
138
+ if (typeof honestySpec.minResourceChanges !== 'number') {
139
+ return;
140
+ }
141
+ const count = Number(honesty.resourceChangeCount || 0);
142
+ const passed = count >= honestySpec.minResourceChanges;
143
+ const softChange = soft || honestySpec.softResourceChanges === true;
144
+ pushHonestyAssertion(
145
+ assertions,
146
+ 'expected.honesty.minResourceChanges',
147
+ softChange ? true : passed,
148
+ passed
149
+ ? `resourceChangeCount ${count} >= ${honestySpec.minResourceChanges}.`
150
+ : `resourceChangeCount ${count} < ${honestySpec.minResourceChanges}${
151
+ softChange ? ' (soft — warning only)' : ''
152
+ }.`
153
+ );
154
+ if (softChange && !passed) {
155
+ assertions[assertions.length - 1].warn = true;
156
+ assertions[assertions.length - 1].soft = true;
157
+ }
158
+ }
159
+
160
+ function evaluateHonestyExpectations(honestySpec, observation, options = {}) {
161
+ if (!honestySpec || typeof honestySpec !== 'object' || Array.isArray(honestySpec)) {
162
+ return [];
163
+ }
164
+ const soft = options.soft === true;
165
+ const honesty = observation.honesty || {};
166
+ const assertions = [];
167
+ if (honestySpec.requireWorkResult !== false) {
168
+ assertWorkResultPresent(assertions, honesty, observation);
169
+ }
170
+ if (!honesty.present) {
171
+ // Missing Output is always a hard failure when required — soft does not waive it.
172
+ return assertions;
173
+ }
174
+ assertSchemaVersion(assertions, honestySpec, honesty);
175
+ assertCompletion(assertions, honestySpec, honesty);
176
+ assertContribution(assertions, honestySpec, honesty);
177
+ assertMinResourceChanges(assertions, honestySpec, honesty, soft);
178
+ return assertions;
179
+ }
180
+
181
+ module.exports = {
182
+ buildHonestyObservation,
183
+ evaluateHonestyExpectations
184
+ };