@aifabrix/builder 2.60.0 → 2.61.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -11
- package/docs/README.md +80 -0
- package/docs/builder-help/evidence-patterns.json +155 -0
- package/docs/builder-help/golden-examples/crm-company.json +30 -0
- package/docs/builder-help/golden-examples/crm-deal.json +29 -0
- package/docs/builder-help/golden-examples/document-storage-keyed-get.json +85 -0
- package/docs/builder-help/golden-examples/document-storage.json +30 -0
- package/docs/builder-help/golden-examples/meeting-transcript.json +29 -0
- package/docs/builder-help/golden-examples/repository-template.json +29 -0
- package/docs/builder-help/golden-examples/service-ticket.json +29 -0
- package/docs/builder-help/platform-roles.json +98 -0
- package/docs/builder-help/resource-type-catalog.json +402 -0
- package/lib/api/configuration.api.js +131 -0
- package/lib/api/system-secrets.api.js +72 -0
- package/lib/app/run-docker-fallback.js +6 -1
- package/lib/app/run-helpers.js +2 -1
- package/lib/app/run-parameter-sync.js +142 -0
- package/lib/build/docker-build-args.js +5 -2
- package/lib/build/index.js +3 -2
- package/lib/build/standard-docker-build.js +2 -2
- package/lib/cli/setup-app.js +5 -0
- package/lib/cli/setup-environment.js +156 -0
- package/lib/commands/datasource-capability-upsert-cli.js +112 -0
- package/lib/commands/datasource-capability.js +4 -2
- package/lib/commands/env-secret-context.js +113 -0
- package/lib/commands/env-secret-list.js +200 -0
- package/lib/commands/env-secret-push-confirm.js +54 -0
- package/lib/commands/env-secret-push-run.js +227 -0
- package/lib/commands/env-secret-push.js +168 -0
- package/lib/commands/repair-datasource-apply.js +2 -0
- package/lib/commands/repair-datasource-keyed-document.js +122 -0
- package/lib/commands/repair-datasource-run.js +1 -0
- package/lib/commands/setup-modes.js +1 -8
- package/lib/commands/setup-prompts.js +2 -180
- package/lib/commands/verify-operations-skip-e2e.js +25 -1
- package/lib/commands/verify-operations-steps.js +13 -1
- package/lib/commands/wizard-config-normalizer.js +7 -4
- package/lib/commands/wizard-core.js +5 -157
- package/lib/commands/wizard-file-saving.js +163 -0
- package/lib/core/env-platform-expand.js +5 -1
- package/lib/core/secrets-env-content.js +5 -1
- package/lib/core/secrets-env-write.js +10 -3
- package/lib/core/secrets-load.js +4 -2
- package/lib/datasource/binary-documents-validator.js +190 -0
- package/lib/datasource/capability/run-capability-upsert.js +202 -0
- package/lib/datasource/capability/upsert-ingredients.js +291 -0
- package/lib/datasource/capability/upsert-operations.js +138 -0
- package/lib/datasource/capability/upsert-test-scaffold.js +189 -0
- package/lib/datasource/validate.js +12 -5
- package/lib/generator/index.js +3 -0
- package/lib/lifecycle/product-model.js +4 -3
- package/lib/lifecycle/report-display.js +3 -2
- package/lib/parameters/infra-parameter-catalog.js +1 -1
- package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +1 -1
- package/lib/programmatic/builder-help-governance.js +1 -1
- package/lib/programmatic/builder-help.js +1 -1
- package/lib/role-assistant/test-runner-workhub-answers.js +4 -1
- package/lib/role-assistant/test-runner-workhub-missing-fields.js +42 -0
- package/lib/role-assistant/test-runner-workhub-wait-stop.js +94 -0
- package/lib/role-assistant/test-runner-workhub.js +28 -19
- package/lib/schema/application-schema.json +14 -2
- package/lib/schema/external-datasource.schema.json +23 -3
- package/lib/schema/infra.parameter.yaml +388 -38
- package/lib/utils/compose-generate-docker-compose.js +7 -12
- package/lib/utils/datasource-binary-evidence.js +92 -0
- package/lib/utils/datasource-test-run-capability-scope.js +44 -1
- package/lib/utils/datasource-test-run-debug-display.js +2 -0
- package/lib/utils/datasource-test-run-display.js +8 -2
- package/lib/utils/datasource-test-run-issue-guidance.js +176 -0
- package/lib/utils/datasource-test-run-tty-log.js +2 -0
- package/lib/utils/env-copy.js +11 -10
- package/lib/utils/external-system-system-test-tty.js +3 -2
- package/lib/utils/image-tags.js +2 -2
- package/lib/utils/platform-kv-ref.js +1 -1
- package/lib/utils/prepare-local-data-mount.js +58 -0
- package/lib/utils/secrets-helpers.js +0 -1
- package/lib/utils/system-secret-mapping.js +125 -0
- package/lib/utils/test-log-writer.js +2 -1
- package/lib/validation/external-manifest-validator.js +5 -0
- package/lib/validation/openapi-contract-surface-validator.js +3 -1
- package/lib/validation/validate-external-file.js +5 -1
- package/package.json +4 -3
- package/templates/agent-kit/agent-kit.yaml +1 -1
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +2 -1
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +15 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +3 -2
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +6 -2
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +22 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +7 -1
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/testing-playbook.md +117 -0
- package/templates/agent-kit/skills/shared/interaction.md +83 -0
- package/templates/agent-kit/skills/shared/status.md +3 -12
- package/templates/applications/builder-api/application.yaml +1 -1
- package/templates/applications/builder-api/env.template +5 -1
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/env.template +10 -12
- package/templates/applications/keycloak/application.yaml +6 -1
- package/templates/applications/miso-controller/application.yaml +74 -2
- package/templates/applications/miso-controller/env.template +42 -3
- package/templates/applications/miso-controller/rbac.yaml +17 -0
- package/templates/external-system/external-datasource.yaml.hbs +7 -1
- package/templates/marketplace/main.json +4 -4
- package/templates/python/docker-compose.hbs +1 -1
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +0 -41
- /package/{lib/programmatic/help-content → docs/builder-help/content}/channel-onboarding.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/cip-overview.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/connected-system-ui.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/dimensions-guide.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/enterprise-sync-fabrix.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/overview.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/subscription-guide.md +0 -0
- /package/{lib/programmatic/help-content → docs/builder-help/content}/workflow.md +0 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map an application's `.env` variables onto Miso catalog keys.
|
|
3
|
+
*
|
|
4
|
+
* The `.env` is keyed by environment variable (`MORI_POLICY_PRIVATE_KEY`) while the system
|
|
5
|
+
* secrets API is keyed by catalog key (`secrets-policyPrivateKeyVault`). The mapping is not
|
|
6
|
+
* invented here: it is read from the application's own `env.template`, because the
|
|
7
|
+
* `NAME=kv://<catalogKey>` line is already the declaration that decides where the value is
|
|
8
|
+
* read from at runtime. A second table in the CLI would be free to drift from it.
|
|
9
|
+
*
|
|
10
|
+
* A variable whose template line is not a `kv://` reference is ordinary configuration, not a
|
|
11
|
+
* secret, and is skipped rather than pushed.
|
|
12
|
+
*
|
|
13
|
+
* Note this is the flat `kv://<catalogKey>` form used by the Controller's system secrets.
|
|
14
|
+
* The Dataplane's credential store uses `kv://<systemKey>/<path>`; see
|
|
15
|
+
* `credential-secrets-env-kv.js` for that one. They are not interchangeable.
|
|
16
|
+
*
|
|
17
|
+
* @fileoverview env.template kv:// declarations → catalog keys
|
|
18
|
+
* @author AI Fabrix Team
|
|
19
|
+
* @version 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
/** `NAME=value`, ignoring blank lines, comments and `export ` prefixes. */
|
|
25
|
+
const ASSIGNMENT = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Strip surrounding quotes and trailing whitespace from an env value.
|
|
29
|
+
* @param {string} raw - Raw right-hand side
|
|
30
|
+
* @returns {string} Cleaned value
|
|
31
|
+
*/
|
|
32
|
+
function cleanValue(raw) {
|
|
33
|
+
const trimmed = String(raw === undefined || raw === null ? '' : raw).trim();
|
|
34
|
+
if (trimmed.length >= 2) {
|
|
35
|
+
const first = trimmed[0];
|
|
36
|
+
const last = trimmed[trimmed.length - 1];
|
|
37
|
+
if ((first === '"' && last === '"') || (first === '\'' && last === '\'')) {
|
|
38
|
+
return trimmed.slice(1, -1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return trimmed;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parse `NAME=value` lines into a Map, last assignment winning.
|
|
46
|
+
* @param {string} content - File content
|
|
47
|
+
* @returns {Map<string, string>} Variable name → value
|
|
48
|
+
*/
|
|
49
|
+
function parseEnvAssignments(content) {
|
|
50
|
+
const out = new Map();
|
|
51
|
+
for (const line of String(content || '').split(/\r?\n/)) {
|
|
52
|
+
if (!line || /^\s*#/.test(line)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const match = line.match(ASSIGNMENT);
|
|
56
|
+
if (match) {
|
|
57
|
+
out.set(match[1], cleanValue(match[2]));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Catalog keys declared by an `env.template`, keyed by environment variable name.
|
|
65
|
+
* Only `kv://` lines are secrets; everything else is skipped.
|
|
66
|
+
* @param {string} templateContent - env.template content
|
|
67
|
+
* @returns {Map<string, string>} Variable name → catalog key
|
|
68
|
+
*/
|
|
69
|
+
function catalogKeysFromTemplate(templateContent) {
|
|
70
|
+
const out = new Map();
|
|
71
|
+
for (const [name, value] of parseEnvAssignments(templateContent)) {
|
|
72
|
+
if (!value.startsWith('kv://')) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const catalogKey = value.slice('kv://'.length).trim();
|
|
76
|
+
if (catalogKey && !catalogKey.includes('/')) {
|
|
77
|
+
out.set(name, catalogKey);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Pair the values in a `.env` with the catalog keys its `env.template` declares.
|
|
85
|
+
*
|
|
86
|
+
* Skipped rows are returned rather than dropped, so the command can say why a variable was
|
|
87
|
+
* not pushed instead of silently ignoring it.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} envContent - Operator's .env content
|
|
90
|
+
* @param {string} templateContent - The application's env.template content
|
|
91
|
+
* @param {Object} [options] - `only` restricts to one variable name
|
|
92
|
+
* @returns {{ pushable: Array<Object>, skipped: Array<Object> }} Rows carrying value and catalog key
|
|
93
|
+
*/
|
|
94
|
+
function mapEnvToCatalogKeys(envContent, templateContent, options = {}) {
|
|
95
|
+
const declared = catalogKeysFromTemplate(templateContent);
|
|
96
|
+
const values = parseEnvAssignments(envContent);
|
|
97
|
+
const only = options.only ? String(options.only).trim() : '';
|
|
98
|
+
const pushable = [];
|
|
99
|
+
const skipped = [];
|
|
100
|
+
for (const [name, value] of values) {
|
|
101
|
+
if (only && name !== only) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const catalogKey = declared.get(name);
|
|
105
|
+
if (!catalogKey) {
|
|
106
|
+
skipped.push({ name, reason: 'not a kv:// reference in env.template' });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (!value) {
|
|
110
|
+
skipped.push({ name, catalogKey, reason: 'no value in the env file' });
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
pushable.push({ name, catalogKey, value });
|
|
114
|
+
}
|
|
115
|
+
if (only && pushable.length === 0 && skipped.length === 0) {
|
|
116
|
+
skipped.push({ name: only, reason: 'not present in the env file' });
|
|
117
|
+
}
|
|
118
|
+
return { pushable, skipped };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
parseEnvAssignments,
|
|
123
|
+
catalogKeysFromTemplate,
|
|
124
|
+
mapEnvToCatalogKeys
|
|
125
|
+
};
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const fs = require('fs').promises;
|
|
11
11
|
const path = require('path');
|
|
12
|
+
const { sanitizeBinaryEvidence } = require('./datasource-binary-evidence');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Prepare object for JSON serialization (handles circular refs)
|
|
@@ -45,7 +46,7 @@ async function writeTestLog(appKey, data, logType = 'test-integration', integrat
|
|
|
45
46
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
46
47
|
const filename = `${logType}-${timestamp}.json`;
|
|
47
48
|
const filePath = path.join(logsDir, filename);
|
|
48
|
-
const sanitized = sanitizeForLog(data);
|
|
49
|
+
const sanitized = sanitizeForLog(sanitizeBinaryEvidence(data));
|
|
49
50
|
await fs.writeFile(filePath, JSON.stringify(sanitized, null, 2), 'utf8');
|
|
50
51
|
return filePath;
|
|
51
52
|
}
|
|
@@ -16,6 +16,7 @@ const path = require('path');
|
|
|
16
16
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
17
17
|
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
18
18
|
const { validateAbac } = require('../datasource/abac-validator');
|
|
19
|
+
const { validateBinaryDocumentsContract } = require('../datasource/binary-documents-validator');
|
|
19
20
|
const { validateManifestRuntimeConfiguration } = require('./runtime-configuration-rules');
|
|
20
21
|
const { validateAppContractSurface } = require('./openapi-contract-surface-validator');
|
|
21
22
|
|
|
@@ -147,9 +148,13 @@ function validateDatasources(manifest, ajv, externalDatasourceSchema, errors, wa
|
|
|
147
148
|
} else {
|
|
148
149
|
const fieldRefErrors = validateFieldReferences(datasource);
|
|
149
150
|
const abacErrors = validateAbac(datasource);
|
|
151
|
+
const binaryDocuments = validateBinaryDocumentsContract(datasource);
|
|
150
152
|
const prefix = `Datasource ${index + 1} (${datasource.key || 'unknown'}): `;
|
|
151
153
|
fieldRefErrors.forEach(e => errors.push(prefix + e));
|
|
152
154
|
abacErrors.forEach(e => errors.push(prefix + e));
|
|
155
|
+
// Codes are the dataplane's, so the offline answer matches the upload answer.
|
|
156
|
+
binaryDocuments.errors.forEach(e => errors.push(`${prefix}${e.code}: ${e.message}`));
|
|
157
|
+
binaryDocuments.warnings.forEach(w => warnings.push(`${prefix}${w.code}: ${w.message}`));
|
|
153
158
|
}
|
|
154
159
|
});
|
|
155
160
|
}
|
|
@@ -426,5 +426,7 @@ module.exports = {
|
|
|
426
426
|
validateDatasourceFileContractSurface,
|
|
427
427
|
validateVendorOperationContract,
|
|
428
428
|
validateServiceContractDatasourceContracts,
|
|
429
|
-
findVendorOperation
|
|
429
|
+
findVendorOperation,
|
|
430
|
+
resolveVendorOpenApiSpec,
|
|
431
|
+
inferIntegrationContextFromPath
|
|
430
432
|
};
|
|
@@ -111,11 +111,15 @@ function validateDatasourceFileExtras(parsed, filePath) {
|
|
|
111
111
|
const { collectExternalDatasourceWarnings } = require('./datasource-warnings');
|
|
112
112
|
const { validateDatasourceFileContractSurface } = require('./openapi-contract-surface-validator');
|
|
113
113
|
const errors = [...validateFieldReferences(parsed), ...validateAbac(parsed)];
|
|
114
|
+
const { validateBinaryDocumentsContract } = require('../datasource/binary-documents-validator');
|
|
115
|
+
const binary = validateBinaryDocumentsContract(parsed);
|
|
116
|
+
errors.push(...binary.errors.map(issue => `${issue.code}: ${issue.message}`));
|
|
114
117
|
const contractSurface = validateDatasourceFileContractSurface(parsed, filePath);
|
|
115
118
|
errors.push(...contractSurface.errors);
|
|
116
119
|
const warnings = [
|
|
117
120
|
...collectExternalDatasourceWarnings(parsed),
|
|
118
|
-
...contractSurface.warnings
|
|
121
|
+
...contractSurface.warnings,
|
|
122
|
+
...binary.warnings.map(issue => `${issue.code}: ${issue.message}`)
|
|
119
123
|
];
|
|
120
124
|
return { errors, warnings };
|
|
121
125
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.61.2",
|
|
4
4
|
"description": "AI Fabrix Builder — CLI and developer scripts (pnpm + af)",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"bin/aifabrix.js",
|
|
12
12
|
"lib/",
|
|
13
|
+
"docs/builder-help/",
|
|
13
14
|
"templates/",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE"
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
"dev-deploy": "node scripts/pnpm/dev-deploy.mjs",
|
|
25
26
|
"af": "node scripts/pnpm/af.mjs",
|
|
26
27
|
"check-quiet": "node scripts/pnpm/check-quiet.mjs",
|
|
27
|
-
"agent-skills:sync": "node scripts/pnpm/agent-skills-sync.mjs",
|
|
28
|
+
"agent-skills:sync": "node scripts/pnpm/agent-skills-sync.mjs --codex-home",
|
|
28
29
|
"agent-skills:check": "node scripts/pnpm/agent-skills-sync.mjs --check",
|
|
29
30
|
"agent-skills:sync:codex": "node scripts/pnpm/agent-skills-sync.mjs --codex-home",
|
|
30
31
|
"agent-skills:test": "node --test scripts/pnpm/agent-skills-sync.test.mjs",
|
|
@@ -131,7 +132,7 @@
|
|
|
131
132
|
}
|
|
132
133
|
},
|
|
133
134
|
"dependencies": {
|
|
134
|
-
"@aifabrix/miso-client": "
|
|
135
|
+
"@aifabrix/miso-client": "5.0.3",
|
|
135
136
|
"@azure/identity": "4.11.1",
|
|
136
137
|
"adm-zip": "^0.6.1",
|
|
137
138
|
"ajv": "^8.20.0",
|
|
@@ -20,7 +20,7 @@ Resolve phase: explicit argument → ask. Package state informs the recommendati
|
|
|
20
20
|
the action.
|
|
21
21
|
|
|
22
22
|
Stop at the phase gate. Do not run the next phase without `next-yes`
|
|
23
|
-
([interaction.md](../
|
|
23
|
+
([interaction.md](../shared/interaction.md)).
|
|
24
24
|
|
|
25
25
|
| Phase | Entry | Success |
|
|
26
26
|
| --- | --- | --- |
|
|
@@ -67,6 +67,7 @@ System key: argument → active plan → sole `integration/` folder → ask once
|
|
|
67
67
|
|
|
68
68
|
## References
|
|
69
69
|
|
|
70
|
+
- [interaction.md](../shared/interaction.md) — native selection controls, routes, and phase gates
|
|
70
71
|
- [status.md](../shared/status.md) — read-only default, route options, status matrix
|
|
71
72
|
- [delivery-gates.md](references/delivery-gates.md) — BID/wizard/repair, upload vs deploy, tests, identity, protection
|
|
72
73
|
- [contract-checklist.md](references/contract-checklist.md) — exposed, FK, viewpoints, RBAC/ABAC
|
|
@@ -39,6 +39,21 @@ If `integration/<systemKey>/deploy.js` exists, you may run it as the publish lad
|
|
|
39
39
|
|
|
40
40
|
Never mark live E2E pass when it did not run.
|
|
41
41
|
|
|
42
|
+
## Upsert authoring and warnings
|
|
43
|
+
|
|
44
|
+
When upsert is explicitly required, first run
|
|
45
|
+
`aifabrix datasource capability upsert <file-or-key> --dry-run --json`. Apply a
|
|
46
|
+
fix automatically only when the finding identifies a deterministic local
|
|
47
|
+
manifest change and the active phase authorizes mutation. Rerun the exact
|
|
48
|
+
failed command before broader validation.
|
|
49
|
+
|
|
50
|
+
Every open finding must state the observed condition, business consequence,
|
|
51
|
+
safe action, prevention, residual risk, and exact rerun. A source API that
|
|
52
|
+
cannot constrain the complete business identity is not AI-fixable: keep valid
|
|
53
|
+
separate create/update capabilities, report duplicate or wrong-update risk,
|
|
54
|
+
and withhold verified upsert. Never invent a lookup, weaken the two-write
|
|
55
|
+
no-duplicate assertion, or hide the warning behind another passing test.
|
|
56
|
+
|
|
42
57
|
## Identity and protection order
|
|
43
58
|
|
|
44
59
|
1. `aifabrix auth status` — if unauthenticated, [login.md](../../shared/login.md)
|
|
@@ -16,7 +16,7 @@ Named with no specification, report what exists and ask; do not start writing a
|
|
|
16
16
|
an inferred spec ([status.md](../shared/status.md)).
|
|
17
17
|
|
|
18
18
|
Score completeness with [challenge-checklist.md](references/challenge-checklist.md).
|
|
19
|
-
|
|
19
|
+
Structured choices and phase gates: [interaction.md](../shared/interaction.md).
|
|
20
20
|
Host runtimes (local vs SSH): [hosts.md](../shared/hosts.md).
|
|
21
21
|
CLI login from chat: [login.md](../shared/login.md).
|
|
22
22
|
|
|
@@ -32,7 +32,8 @@ Do not start Connected System validate until **PLAN_READY** and the user picks `
|
|
|
32
32
|
|
|
33
33
|
1. Collect the spec the user named. Do not mine platform repos as the spec.
|
|
34
34
|
2. Inventory without adding: purpose, sources, entities, relationships, role labels, operations, Viewpoints, Evidence, identity join. Missing sections → `TBD` plus an Open question.
|
|
35
|
-
3. Challenge required rows.
|
|
35
|
+
3. Challenge required rows. Use the structured question control for every MISSING required
|
|
36
|
+
row. Authority and identity cannot be guessed.
|
|
36
37
|
4. Write or update `.cursor/plans/{major}.0-{slug}.plan.md` using the template H2 order. Same capability updates in place.
|
|
37
38
|
5. Report status and path. On PLAN_READY, offer validate — do not run it without `next-yes`.
|
|
38
39
|
|
|
@@ -38,8 +38,10 @@ business-case readiness. None of them, alone or together, makes prove READY.
|
|
|
38
38
|
|
|
39
39
|
Every phase **must** update [learning-template.md](references/learning-template.md).
|
|
40
40
|
Evidence rules: [evidence-lifecycle.md](references/evidence-lifecycle.md).
|
|
41
|
+
Role Assistant test execution and diagnosis:
|
|
42
|
+
[testing-playbook.md](../aifabrix-role-assistant/references/testing-playbook.md).
|
|
41
43
|
Demo shape: [demo-template.md](references/demo-template.md).
|
|
42
|
-
|
|
44
|
+
Structured choices and phase gates: [interaction.md](../shared/interaction.md).
|
|
43
45
|
Host runtimes (local vs SSH): [hosts.md](../shared/hosts.md).
|
|
44
46
|
CLI login from chat: [login.md](../shared/login.md).
|
|
45
47
|
|
|
@@ -60,7 +62,9 @@ Repeatable: demo, Knowledge, candidate Evidence, tests. Do not refuse because va
|
|
|
60
62
|
|
|
61
63
|
## Prove
|
|
62
64
|
|
|
63
|
-
Run assistant tests
|
|
65
|
+
Run assistant tests using the testing playbook. Record the business verdict,
|
|
66
|
+
execution reference, and gap owner (`none` | `product-gap` |
|
|
67
|
+
`missing-customer-fact` | `scope-decision`).
|
|
64
68
|
Happy + safe-stop coverage for authority scenarios.
|
|
65
69
|
Never report candidates as certified.
|
|
66
70
|
|
|
@@ -49,6 +49,25 @@ Promote candidate → governed Evidence only when:
|
|
|
49
49
|
3. Contract validation + certification path for Evidence completed (public Evidence Fabrix / operate-first RA docs)
|
|
50
50
|
4. learning.md records promotion date + commit
|
|
51
51
|
|
|
52
|
+
## Human authority and applied proof
|
|
53
|
+
|
|
54
|
+
Keep these states distinct:
|
|
55
|
+
|
|
56
|
+
| State | What it proves |
|
|
57
|
+
| --- | --- |
|
|
58
|
+
| Candidate or proposal | Draft content exists; it is not governed Evidence |
|
|
59
|
+
| Certified | The applicable human governance decision completed |
|
|
60
|
+
| Active | The product may supply the Evidence to execution |
|
|
61
|
+
| Applied | A recorded execution shows the Evidence affected the result |
|
|
62
|
+
|
|
63
|
+
An agent may prepare candidates, execute authorized source cases, and inspect a
|
|
64
|
+
proposal. It must pause before certifying, activating, rejecting, or
|
|
65
|
+
deactivating Evidence unless the current user explicitly authorizes that action
|
|
66
|
+
and the product workflow permits it. Record the pause as `BLOCKED_BY_HUMAN`, not
|
|
67
|
+
as a failed test. After the human gate, rerun the case and prove Applied Evidence
|
|
68
|
+
from execution evidence; catalog presence is not Applied proof. Follow the
|
|
69
|
+
[Role Assistant testing playbook](../../aifabrix-role-assistant/references/testing-playbook.md).
|
|
70
|
+
|
|
52
71
|
## Tests
|
|
53
72
|
|
|
54
73
|
For each in-scope scenario ID:
|
|
@@ -66,3 +85,6 @@ Prefer `role-assistant/ra-<roleKey>/tests/<suiteId>/` in this customer repo (pac
|
|
|
66
85
|
- Hiding process law in Knowledge
|
|
67
86
|
- Uploading candidates as if certified
|
|
68
87
|
- Skipping safe-stop coverage for authority scenarios
|
|
88
|
+
- Certifying, activating, rejecting, or deactivating Evidence without the
|
|
89
|
+
current user's explicit authority
|
|
90
|
+
- Reporting catalog presence as proof that Evidence was Applied
|
|
@@ -9,8 +9,11 @@ description: >
|
|
|
9
9
|
# aifabrix-role-assistant
|
|
10
10
|
|
|
11
11
|
See [package-boundary.md](references/package-boundary.md) and nested `role-assistant/AGENTS.md`.
|
|
12
|
+
For test execution, verdicts, fixtures, and diagnosis, follow
|
|
13
|
+
[testing-playbook.md](references/testing-playbook.md).
|
|
12
14
|
Host runtimes (local vs SSH): [hosts.md](../shared/hosts.md).
|
|
13
15
|
CLI login from chat: [login.md](../shared/login.md).
|
|
16
|
+
Structured choices and phase gates: [interaction.md](../shared/interaction.md).
|
|
14
17
|
|
|
15
18
|
Named with no task, report status and stop: [status.md](../shared/status.md).
|
|
16
19
|
|
|
@@ -47,7 +50,9 @@ substitutes for it.
|
|
|
47
50
|
|
|
48
51
|
1. `aifabrix download <catalogRoleOrRaKey>` before editing an existing assistant.
|
|
49
52
|
2. Author settings, Knowledge, Evidence, tests, and sidecars per current Builder contracts. Read `aifabrix role-assistant --help`.
|
|
50
|
-
3. `aifabrix role-assistant test …` is allowed without local RA publish.
|
|
53
|
+
3. `aifabrix role-assistant test …` is allowed without local RA publish. Apply
|
|
54
|
+
the testing playbook and inspect hard business assertions before reporting
|
|
55
|
+
READY or VERIFIED.
|
|
51
56
|
4. Upload/deploy RA only when the user explicitly asks in this turn.
|
|
52
57
|
5. Report results honestly.
|
|
53
58
|
|
|
@@ -62,3 +67,4 @@ substitutes for it.
|
|
|
62
67
|
## Trigger examples
|
|
63
68
|
|
|
64
69
|
- Create or update the Finance Controller Role Assistant
|
|
70
|
+
- Test or diagnose the Finance Controller Role Assistant
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Role Assistant testing and diagnosis
|
|
2
|
+
|
|
3
|
+
Public concepts: https://docs.aifabrix.ai/docs/role-assistants
|
|
4
|
+
Exact commands, fields, and flags: run `aifabrix role-assistant test --help` with
|
|
5
|
+
the installed Builder version.
|
|
6
|
+
|
|
7
|
+
Use this playbook for live Role Assistant cases. A successful command is not
|
|
8
|
+
enough: the observed business outcome, authority boundary, capabilities, Work
|
|
9
|
+
Result, and resource changes must match the case.
|
|
10
|
+
|
|
11
|
+
## Preconditions
|
|
12
|
+
|
|
13
|
+
- Authenticate to the intended environment and identify the package and cases
|
|
14
|
+
root before execution.
|
|
15
|
+
- Confirm every required Connected System is published and certified, its
|
|
16
|
+
required capabilities are available, and worker availability is known.
|
|
17
|
+
- Record the actor and business role, mutation scope, designated test subjects,
|
|
18
|
+
and cleanup rule before a mutating case.
|
|
19
|
+
- Treat missing auth, worker availability, capability, fixture, or required
|
|
20
|
+
human action as `BLOCKED` with the exact prerequisite.
|
|
21
|
+
|
|
22
|
+
## Execution ladder
|
|
23
|
+
|
|
24
|
+
1. Validate the package and use `--list-cases` to confirm discovery.
|
|
25
|
+
2. Run one focused case with `--case ... --json`.
|
|
26
|
+
3. Inspect lifecycle and final Runtime status, questions or approvals,
|
|
27
|
+
`expected.capabilities`, Work Result completion, resource changes, and
|
|
28
|
+
Evidence use. Do not rely on the process exit or wrapper verdict alone.
|
|
29
|
+
4. Correct the owning layer, rerun the exact case, and then run its suite.
|
|
30
|
+
5. Run broader suites only after the focused case is stable.
|
|
31
|
+
6. Record environment, timestamp, package/source revision, command,
|
|
32
|
+
execution/correlation reference, verdict class, and gap owner in
|
|
33
|
+
`learning/learning.md` or the plan-defined evidence location.
|
|
34
|
+
|
|
35
|
+
## Verdict law
|
|
36
|
+
|
|
37
|
+
| Observation | Verdict |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| Hard assertions and intended business outcome pass | `PASS` |
|
|
40
|
+
| Intended denial or safe stop occurs with no forbidden mutation | `PASS_EXPECTED_STOP` |
|
|
41
|
+
| `expected.soft: true` turns a mismatch into a warning | `GAP`; never `VERIFIED` |
|
|
42
|
+
| A prerequisite or required human action is absent | `BLOCKED` with the missing row |
|
|
43
|
+
| Runtime or CLI is defective and the run is reproducible | `PRODUCT_GAP` |
|
|
44
|
+
| Role Assistant, Knowledge, or Evidence content is wrong while the product behaves correctly | `PACKAGE_GAP` |
|
|
45
|
+
|
|
46
|
+
An exit code `0`, CLI `PASS`, lifecycle smoke, or certification level cannot
|
|
47
|
+
replace the applicable business verdict. An expected safe stop is not ordinary
|
|
48
|
+
success: name the denied or waiting state and prove that no forbidden mutation
|
|
49
|
+
occurred.
|
|
50
|
+
|
|
51
|
+
## Assertion quality
|
|
52
|
+
|
|
53
|
+
- Release and prove cases use hard lifecycle and Result assertions. Soft cases
|
|
54
|
+
are exploratory and cannot establish READY or VERIFIED.
|
|
55
|
+
- Mutation cases assert the exact required and forbidden capabilities,
|
|
56
|
+
`expected.honesty.requireWorkResult`, completion, and a meaningful
|
|
57
|
+
`expected.honesty.minResourceChanges` value.
|
|
58
|
+
- Read-only cases forbid mutation capabilities. Authority cases assert the
|
|
59
|
+
intended denial, question, approval wait, or safe stop.
|
|
60
|
+
- Do not weaken an assertion to accommodate a failure. Classify the gap and
|
|
61
|
+
repair its owner.
|
|
62
|
+
|
|
63
|
+
## Fixtures, identity, and cleanup
|
|
64
|
+
|
|
65
|
+
- Stable shared identities are read-only unless the integration README names
|
|
66
|
+
them as approved mutable subjects.
|
|
67
|
+
- Give mutable cases collision-safe explicit values. Generate and write those
|
|
68
|
+
values into the case through normal repository editing before the run; do not
|
|
69
|
+
claim that an interpolation token exists unless current CLI help, schema,
|
|
70
|
+
source, and tests establish it.
|
|
71
|
+
- Share an identity across cases only for a documented suite dependency.
|
|
72
|
+
- Never inject a hidden primary key, actor, business role, API key, or
|
|
73
|
+
authorization dimension to make a case pass.
|
|
74
|
+
- Cleanup must be explicit, bounded to the designated subject, and separately
|
|
75
|
+
authorized when destructive.
|
|
76
|
+
|
|
77
|
+
## ABAC and replay
|
|
78
|
+
|
|
79
|
+
Every authority-sensitive scenario needs an allowed case and an outside-scope
|
|
80
|
+
or denied case. Nested calls must preserve the same actor and business-role
|
|
81
|
+
context. Ambiguous identity must ask or stop safely, never select a convenient
|
|
82
|
+
record. Retry and replay cases must prove there is no duplicate resource and no
|
|
83
|
+
double-counted Evidence.
|
|
84
|
+
|
|
85
|
+
## Human Evidence boundary
|
|
86
|
+
|
|
87
|
+
Agents may author candidates, run source executions, and inspect proposals when
|
|
88
|
+
authorized. They must not certify, activate, reject, or deactivate Evidence for
|
|
89
|
+
a human unless the current user explicitly authorizes that product action and
|
|
90
|
+
the product workflow permits it. A run paused at certification or activation is
|
|
91
|
+
`BLOCKED_BY_HUMAN`, not failed. Later proof must show Evidence was actually
|
|
92
|
+
Applied in execution; catalog presence alone is insufficient. See
|
|
93
|
+
[Evidence lifecycle](../../aifabrix-prove/references/evidence-lifecycle.md).
|
|
94
|
+
|
|
95
|
+
## Root-cause routing
|
|
96
|
+
|
|
97
|
+
| Finding | Owner / next action |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| Auth, environment, or worker unavailable | Report the exact prerequisite |
|
|
100
|
+
| Duplicate or stale test data | Fixture owner; preserve the trail and repair safely |
|
|
101
|
+
| Soft or incomplete expectation | Case author; strengthen without changing product behavior |
|
|
102
|
+
| Missing operation, certification, or capability | Connected System package |
|
|
103
|
+
| Runtime loop, wrong identity binding, or false success | Product gap with execution evidence |
|
|
104
|
+
| Wrong prompt, Knowledge, or Evidence definition | Role Assistant package |
|
|
105
|
+
| Evidence certification or activation required | Human governance gate |
|
|
106
|
+
|
|
107
|
+
Do not conceal a lower-layer gap in Knowledge or build a Role Assistant-local
|
|
108
|
+
imitation of a missing Connected System capability.
|
|
109
|
+
|
|
110
|
+
For an upsert finding, route local manifest repair to Connected System
|
|
111
|
+
ownership and rerun the exact failed proof. If the external source cannot
|
|
112
|
+
support exact business-identity lookup or uniqueness, state what happened,
|
|
113
|
+
what cannot be repaired by AI, the duplicate or wrong-record-update risk, the
|
|
114
|
+
safe alternative, and how future connectors should prevent it. Keep readiness
|
|
115
|
+
blocked or qualified as reported by validation; never substitute create,
|
|
116
|
+
weaken the no-duplicate assertion, or clear the warning because an unrelated
|
|
117
|
+
case passed.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Structured choices and phase gates
|
|
2
|
+
|
|
3
|
+
This file owns interactive choices for every Agent Kit skill. Use the same behavior in
|
|
4
|
+
Cursor, Claude, and Codex; host-specific tool names do not change the workflow.
|
|
5
|
+
|
|
6
|
+
## Show choices in the host control
|
|
7
|
+
|
|
8
|
+
When the user must choose between discrete actions, invoke the host's native structured
|
|
9
|
+
question control instead of printing a `Choose:` block in chat:
|
|
10
|
+
|
|
11
|
+
| Host | Native control |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Cursor | `AskQuestion` |
|
|
14
|
+
| Claude | `AskUserQuestion` |
|
|
15
|
+
| Codex | `request_user_input` |
|
|
16
|
+
|
|
17
|
+
Give the control a short header, one direct question, and mutually exclusive options.
|
|
18
|
+
Put the recommended option first, label it `(Recommended)`, and add one short description
|
|
19
|
+
of its effect. Keep the stable option ids below as the workflow result even when a host
|
|
20
|
+
returns a label rather than an id.
|
|
21
|
+
|
|
22
|
+
If the host supplies its own free-form **Other** choice, map that response to the matching
|
|
23
|
+
`*-other` id. Otherwise include an explicit **Something else** option. If no structured
|
|
24
|
+
question control is available, show the same choices as a numbered list and wait for one
|
|
25
|
+
answer. Never continue merely because an option was recommended.
|
|
26
|
+
|
|
27
|
+
Do not open a control when the user already made an unambiguous choice in the current
|
|
28
|
+
turn. Treat that choice exactly like the corresponding control result.
|
|
29
|
+
|
|
30
|
+
## Bare-invocation routes
|
|
31
|
+
|
|
32
|
+
Ask once and proceed only on an explicit choice.
|
|
33
|
+
|
|
34
|
+
| Option id | Control label | Means |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `route-normal` | Run normal path (Recommended) | Run the normal path for this skill through to its gate, stopping at each phase gate |
|
|
37
|
+
| `route-check` | Inspect and test only | Run validation, checks, and status with no publish or promotion |
|
|
38
|
+
| `route-other` | Something else | Collect the action in the control's free-form response |
|
|
39
|
+
| `next-stop` | Stop here | End without further action |
|
|
40
|
+
|
|
41
|
+
`route-normal` still stops at every phase gate and still needs `next-yes` to continue. It
|
|
42
|
+
is a route, not permission to run the whole lifecycle unattended.
|
|
43
|
+
|
|
44
|
+
## After success
|
|
45
|
+
|
|
46
|
+
Offer the next eligible phase with the structured question control. Proceed only on
|
|
47
|
+
`next-yes`.
|
|
48
|
+
|
|
49
|
+
Shared option ids: `next-yes` · `next-no` · `next-stop`.
|
|
50
|
+
|
|
51
|
+
| Completed | Next offer |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| aifabrix-plan PLAN_READY | connected-system validate |
|
|
54
|
+
| connected-system READY | connected-system build |
|
|
55
|
+
| connected-system BUILT | connected-system publish |
|
|
56
|
+
| connected-system PASS or PASS_WITH_SKIPS | archive (separate) and/or prove validate |
|
|
57
|
+
| prove READY / BUILT / UPDATED | prove next phase |
|
|
58
|
+
| prove PASS or PASS_WITH_SKIPS | iterate validate/build |
|
|
59
|
+
|
|
60
|
+
Archive is a distinct user decision (`archive-yes` / `archive-no`). Never archive as a
|
|
61
|
+
side effect of PASS.
|
|
62
|
+
|
|
63
|
+
## On gaps
|
|
64
|
+
|
|
65
|
+
- NEEDS_DECISIONS: ask about every challenge row with the structured control. No
|
|
66
|
+
`cust-next`.
|
|
67
|
+
- BLOCKED / FAIL / NEEDS_FIXES / ABORTED: do not offer the next phase as if success.
|
|
68
|
+
|
|
69
|
+
A phase gate is per-gate, not overall. Offer the next phase only when the **Delivery** row
|
|
70
|
+
supports it; a passing package gate beside `Delivery: NEEDS_FIXES` is not success and the
|
|
71
|
+
offer must name what is still open.
|
|
72
|
+
|
|
73
|
+
## Phase detection (connected-system and prove)
|
|
74
|
+
|
|
75
|
+
1. Explicit phase from the user
|
|
76
|
+
2. Ask with the structured control, offering the bare-invocation routes above
|
|
77
|
+
|
|
78
|
+
There is no third step. Package and plan state decide what you *recommend*, never what you
|
|
79
|
+
run: a bare invocation reports status and stops ([status.md](status.md)). Inferring "the
|
|
80
|
+
safe next eligible phase" is what makes a skill start working before the user has said
|
|
81
|
+
what they want.
|
|
82
|
+
|
|
83
|
+
Never silently run the following phase after success.
|
|
@@ -25,18 +25,9 @@ they cannot see coming.
|
|
|
25
25
|
|
|
26
26
|
## Offer the route, do not choose it
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
| --- | --- |
|
|
32
|
-
| `route-normal` | Run the normal path for this skill through to its gate, stopping at each phase gate |
|
|
33
|
-
| `route-check` | Inspect and test only — validation, checks and status, no publish or promotion |
|
|
34
|
-
| `route-other` | Something else; ask what |
|
|
35
|
-
| `next-stop` | Stop here |
|
|
36
|
-
|
|
37
|
-
`route-normal` still stops at every phase gate and still needs `next-yes` to continue
|
|
38
|
-
([interaction.md](../aifabrix-plan/references/interaction.md)). It is a route, not a
|
|
39
|
-
licence to run the whole lifecycle unattended.
|
|
28
|
+
Use the host's native selection control and the canonical route options in
|
|
29
|
+
[interaction.md](interaction.md). Proceed only on an explicit choice. Do not print a
|
|
30
|
+
`Choose:` block when a structured question control is available.
|
|
40
31
|
|
|
41
32
|
## Always report the combined matrix
|
|
42
33
|
|
|
@@ -5,7 +5,7 @@ app:
|
|
|
5
5
|
description: 'Business Transformation services — HTTP orchestration for connected-system workspace lifecycle via Dataplane Enterprise MCP and governance APIs.'
|
|
6
6
|
type: webapp
|
|
7
7
|
language: typescript
|
|
8
|
-
version: 2.
|
|
8
|
+
version: 2.61.2
|
|
9
9
|
|
|
10
10
|
# Image Configuration
|
|
11
11
|
image:
|
|
@@ -23,11 +23,15 @@ MAX_UPLOAD_TIMEOUT_MS=300000
|
|
|
23
23
|
# =============================================================================
|
|
24
24
|
# url:// resolves after kv:// at resolve time (see docs/configuration/resolve-running-urls.md)
|
|
25
25
|
|
|
26
|
+
# Governed configuration uses per-application client credentials by default. The SDK loads
|
|
27
|
+
# its bootstrap snapshot and refreshes it automatically within two minutes; consumers decide
|
|
28
|
+
# whether a changed key also requires an internal client or resource to be recreated.
|
|
29
|
+
MISO_AUTH_MODE=client-credentials
|
|
26
30
|
# Registered OAuth client (populated by aifabrix app register / bootstrap — same as dataplane)
|
|
27
31
|
MISO_CLIENTID=kv://builder-api-client-idKeyVault
|
|
28
32
|
MISO_CLIENTSECRET=kv://builder-api-client-secretKeyVault
|
|
29
33
|
|
|
30
|
-
#
|
|
34
|
+
# Private service-to-service controller origin. Public or remote controller origins require HTTPS.
|
|
31
35
|
MISO_CONTROLLER_URL=url://miso-controller-internal
|
|
32
36
|
# Public: OAuth profile and remaining-step links shown to vendors (not Docker DNS)
|
|
33
37
|
MISO_CONTROLLER_PUBLIC_URL=url://miso-controller-public
|
|
@@ -5,7 +5,7 @@ app:
|
|
|
5
5
|
description: "AI Fabrix Dataplane is a secure, in-tenant integration and automation layer that supplies governed, normalized, and explainable enterprise data to AI agents. Using CIP as a declarative standard, it enforces RBAC and ABAC, executes integrations, and exposes trusted data via MCP and OpenAPI."
|
|
6
6
|
type: webapp
|
|
7
7
|
language: python # Explicitly specify Python language
|
|
8
|
-
version: 2.0.
|
|
8
|
+
version: 2.0.79
|
|
9
9
|
# Image Configuration
|
|
10
10
|
# Set tag to match your build (example: aifabrix build dataplane -t 1.0.0).
|
|
11
11
|
# Registry is required so the controller can pull the image (avoids docker-not-found on the controller host).
|