aibvf-check 0.1.0
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/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/cli.js +116 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +110 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.js +96 -0
- package/dist/index.test.js.map +1 -0
- package/package.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Craig Horton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# aibvf-check
|
|
2
|
+
|
|
3
|
+
**SonarQube for AI initiatives.** A CI/CD pre-flight gate that fails the build when a declared AI initiative would not survive a board review — using the deterministic [AI BVF v1.0](https://www.aibvf.com/protocol) engine.
|
|
4
|
+
|
|
5
|
+
The scoring belongs upstream of the slide deck. `aibvf-check` puts it in the one place a team already trusts to block bad work: the pipeline.
|
|
6
|
+
|
|
7
|
+
## 30-second use
|
|
8
|
+
|
|
9
|
+
Add a manifest at your repo root, `.aibvf.json`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"bvf_version": "1.0",
|
|
14
|
+
"organization": { "industry": "financial", "revenue_eur": 400000000 },
|
|
15
|
+
"policy": { "fail_on": ["Stop"], "max_governance_risk": 60, "min_decision_confidence": 50 },
|
|
16
|
+
"initiatives": [
|
|
17
|
+
{ "id": "cx-genai-assistant", "function": "cx", "ai_tier": "gen2", "readiness": "traditional",
|
|
18
|
+
"scores": { "strategic_alignment": 70, "financial_return": 55, "change_enablement": 55, "governance_risk": 45 },
|
|
19
|
+
"signal_completeness": 0.8 }
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Run it:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx aibvf-check
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
It scores every initiative, prints a scorecard, and **exits non-zero if any trips the policy** — so CI goes red.
|
|
31
|
+
|
|
32
|
+
## GitHub Action
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
- uses: Bahamas1717/ai-bvf@v0.7.0
|
|
36
|
+
with:
|
|
37
|
+
manifest: .aibvf.json # optional, this is the default
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The step fails the workflow on any policy violation.
|
|
41
|
+
|
|
42
|
+
## Policy
|
|
43
|
+
|
|
44
|
+
| Field | Effect |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `fail_on` | Classifications that fail the gate. Default `["Stop"]`. Add `"Fix"` to be strict. |
|
|
47
|
+
| `max_governance_risk` | Optional hard ceiling (0–100). A higher `governance_risk` fails, regardless of verdict. |
|
|
48
|
+
| `min_decision_confidence` | Optional floor (0–100). A lower decision confidence fails. |
|
|
49
|
+
|
|
50
|
+
`signal_completeness` (0–1, per initiative) forwards to the engine: estimated inputs honestly haircut confidence and surface a caveat, so a low-evidence initiative can't sail through on a confident-looking number.
|
|
51
|
+
|
|
52
|
+
## Exit codes
|
|
53
|
+
|
|
54
|
+
| Code | Meaning |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `0` | All initiatives cleared the policy. |
|
|
57
|
+
| `1` | One or more policy violations — the gate failed. |
|
|
58
|
+
| `2` | Config error (manifest missing, malformed, or a bad enum value). |
|
|
59
|
+
|
|
60
|
+
## Options
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
aibvf-check [--manifest <path>] [--json]
|
|
64
|
+
-m, --manifest <path> Manifest file (default: .aibvf.json)
|
|
65
|
+
--json Machine-readable JSON instead of the table
|
|
66
|
+
-h, --help Help
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Deterministic, no network, no telemetry. Same inputs → same verdict, every run. Built on [`@aibvf/core`](https://www.npmjs.com/package/@aibvf/core).
|
|
70
|
+
|
|
71
|
+
## License
|
|
72
|
+
|
|
73
|
+
MIT.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aibvf-check CLI entry. Owns all side effects: read the manifest, print the
|
|
4
|
+
* scorecard, and exit with a code CI can gate on.
|
|
5
|
+
*
|
|
6
|
+
* exit 0 all initiatives pass the policy
|
|
7
|
+
* exit 1 one or more initiatives violate the policy (the gate "fails")
|
|
8
|
+
* exit 2 usage / config error (manifest missing, malformed, bad enum)
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* aibvf-check [--manifest <path>] [--json]
|
|
12
|
+
* Defaults to ./.aibvf.json.
|
|
13
|
+
*/
|
|
14
|
+
import { readFileSync } from 'node:fs';
|
|
15
|
+
import { runCheck, lintManifest } from './index.js';
|
|
16
|
+
const BVF_VERSION = '1.0';
|
|
17
|
+
function parseArgs(argv) {
|
|
18
|
+
let manifest = '.aibvf.json';
|
|
19
|
+
let json = false;
|
|
20
|
+
for (let i = 0; i < argv.length; i++) {
|
|
21
|
+
const a = argv[i];
|
|
22
|
+
if (a === '--manifest' || a === '-m')
|
|
23
|
+
manifest = argv[++i];
|
|
24
|
+
else if (a === '--json')
|
|
25
|
+
json = true;
|
|
26
|
+
else if (a === '--help' || a === '-h') {
|
|
27
|
+
printHelp();
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { manifest, json };
|
|
32
|
+
}
|
|
33
|
+
function printHelp() {
|
|
34
|
+
console.log(`aibvf-check — the AI BVF CI/CD pre-flight gate ("SonarQube for AI")
|
|
35
|
+
|
|
36
|
+
Scores the AI initiatives declared in a manifest and fails the build when any
|
|
37
|
+
would not survive a board review.
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
aibvf-check [--manifest <path>] [--json]
|
|
41
|
+
|
|
42
|
+
Options:
|
|
43
|
+
-m, --manifest <path> Manifest file (default: .aibvf.json)
|
|
44
|
+
--json Emit machine-readable JSON instead of a table
|
|
45
|
+
-h, --help Show this help
|
|
46
|
+
|
|
47
|
+
Exit codes: 0 pass 1 gate failed 2 config error
|
|
48
|
+
Docs: https://www.aibvf.com/protocol`);
|
|
49
|
+
}
|
|
50
|
+
function fail(msg) {
|
|
51
|
+
console.error(`aibvf-check: ${msg}`);
|
|
52
|
+
process.exit(2);
|
|
53
|
+
}
|
|
54
|
+
const { manifest: manifestPath, json } = parseArgs(process.argv.slice(2));
|
|
55
|
+
let raw;
|
|
56
|
+
try {
|
|
57
|
+
raw = readFileSync(manifestPath, 'utf8');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
fail(`could not read manifest '${manifestPath}'. Create one or pass --manifest <path>.`);
|
|
61
|
+
}
|
|
62
|
+
let parsed;
|
|
63
|
+
try {
|
|
64
|
+
parsed = JSON.parse(raw);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
fail(`manifest '${manifestPath}' is not valid JSON: ${e instanceof Error ? e.message : e}`);
|
|
68
|
+
}
|
|
69
|
+
const lintErrors = lintManifest(parsed);
|
|
70
|
+
if (lintErrors.length) {
|
|
71
|
+
fail(`manifest '${manifestPath}' is malformed:\n - ${lintErrors.join('\n - ')}`);
|
|
72
|
+
}
|
|
73
|
+
let result;
|
|
74
|
+
try {
|
|
75
|
+
result = runCheck(parsed);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
// score() throws on unknown industry/function/ai_tier/readiness enum values.
|
|
79
|
+
fail(`scoring failed: ${e instanceof Error ? e.message : e}. Check the manifest enums against list_taxonomy.`);
|
|
80
|
+
}
|
|
81
|
+
if (json) {
|
|
82
|
+
console.log(JSON.stringify({ bvf_version: BVF_VERSION, ...result }, null, 2));
|
|
83
|
+
process.exit(result.ok ? 0 : 1);
|
|
84
|
+
}
|
|
85
|
+
// Human-readable scorecard.
|
|
86
|
+
const eur = (n) => `€${Math.round(n / 1e6 * 10) / 10}M`;
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log('AI BVF pre-flight gate · bvf v' + BVF_VERSION);
|
|
89
|
+
console.log('─'.repeat(72));
|
|
90
|
+
for (const r of result.results) {
|
|
91
|
+
const tag = r.violations.length ? '✗' : '✓';
|
|
92
|
+
console.log(`${tag} ${r.id} [${r.classification}] conf ${r.decision_confidence} ${eur(r.net_value_eur.low)}–${eur(r.net_value_eur.high)}`);
|
|
93
|
+
if (r.caveat)
|
|
94
|
+
console.log(` ⚠ ${r.caveat}`);
|
|
95
|
+
for (const v of r.violations)
|
|
96
|
+
console.log(` ✗ ${v}`);
|
|
97
|
+
}
|
|
98
|
+
console.log('─'.repeat(72));
|
|
99
|
+
const policyBits = [
|
|
100
|
+
`fail_on=[${result.policy.fail_on.join(', ')}]`,
|
|
101
|
+
result.policy.max_governance_risk != null ? `max_governance_risk=${result.policy.max_governance_risk}` : null,
|
|
102
|
+
result.policy.min_decision_confidence != null ? `min_decision_confidence=${result.policy.min_decision_confidence}` : null,
|
|
103
|
+
].filter(Boolean).join(' ');
|
|
104
|
+
console.log(`policy: ${policyBits}`);
|
|
105
|
+
if (result.ok) {
|
|
106
|
+
console.log(`\n✓ PASS — ${result.results.length} initiative(s) cleared the gate.`);
|
|
107
|
+
process.exit(0);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
console.log(`\n✗ FAIL — ${result.failures.length} policy violation(s):`);
|
|
111
|
+
for (const f of result.failures)
|
|
112
|
+
console.log(` - ${f}`);
|
|
113
|
+
console.log('\nRaise the weak pillars (or rescope the initiative) and re-run. See recommend_improvements.');
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aibvf-check — the AI BVF CI/CD pre-flight gate.
|
|
3
|
+
*
|
|
4
|
+
* Reads a declared manifest of AI initiatives, scores each one with the
|
|
5
|
+
* deterministic AI BVF engine (@aibvf/core), applies a policy, and reports
|
|
6
|
+
* which initiatives violate it. The executable (cli.ts) turns a violation
|
|
7
|
+
* into a non-zero exit so the build goes red — "SonarQube for AI".
|
|
8
|
+
*
|
|
9
|
+
* This module is pure: no file IO, no process.exit, no console. That keeps
|
|
10
|
+
* the gate logic unit-testable; cli.ts owns the side effects.
|
|
11
|
+
*/
|
|
12
|
+
import { score } from '@aibvf/core';
|
|
13
|
+
const DEFAULT_FAIL_ON = ['Stop'];
|
|
14
|
+
/**
|
|
15
|
+
* Validate the manifest shape enough to score it. Returns a list of human
|
|
16
|
+
* error strings; empty means well-formed. Kept deliberately light — score()
|
|
17
|
+
* itself rejects unknown enums, so this only catches structural gaps.
|
|
18
|
+
*/
|
|
19
|
+
export function lintManifest(m) {
|
|
20
|
+
const errors = [];
|
|
21
|
+
if (typeof m !== 'object' || m === null)
|
|
22
|
+
return ['Manifest must be a JSON object.'];
|
|
23
|
+
const man = m;
|
|
24
|
+
const org = man.organization;
|
|
25
|
+
if (!org || typeof org !== 'object')
|
|
26
|
+
errors.push('organization is required.');
|
|
27
|
+
else {
|
|
28
|
+
if (typeof org.industry !== 'string')
|
|
29
|
+
errors.push('organization.industry is required.');
|
|
30
|
+
if (typeof org.revenue_eur !== 'number')
|
|
31
|
+
errors.push('organization.revenue_eur (number) is required.');
|
|
32
|
+
}
|
|
33
|
+
if (!Array.isArray(man.initiatives) || man.initiatives.length === 0) {
|
|
34
|
+
errors.push('initiatives must be a non-empty array.');
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
man.initiatives.forEach((init, i) => {
|
|
38
|
+
const it = init;
|
|
39
|
+
if (typeof it.id !== 'string')
|
|
40
|
+
errors.push(`initiatives[${i}].id is required.`);
|
|
41
|
+
if (typeof it.function !== 'string')
|
|
42
|
+
errors.push(`initiatives[${i}].function is required.`);
|
|
43
|
+
if (typeof it.ai_tier !== 'string')
|
|
44
|
+
errors.push(`initiatives[${i}].ai_tier is required.`);
|
|
45
|
+
if (typeof it.readiness !== 'string')
|
|
46
|
+
errors.push(`initiatives[${i}].readiness is required.`);
|
|
47
|
+
const sc = it.scores;
|
|
48
|
+
if (!sc || typeof sc !== 'object')
|
|
49
|
+
errors.push(`initiatives[${i}].scores is required.`);
|
|
50
|
+
else {
|
|
51
|
+
for (const p of ['strategic_alignment', 'financial_return', 'change_enablement', 'governance_risk']) {
|
|
52
|
+
if (typeof sc[p] !== 'number')
|
|
53
|
+
errors.push(`initiatives[${i}].scores.${p} (number) is required.`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return errors;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Score every initiative in the manifest and apply the policy.
|
|
62
|
+
* Pure: deterministic, no IO. Throws only if score() rejects an enum value.
|
|
63
|
+
*/
|
|
64
|
+
export function runCheck(manifest) {
|
|
65
|
+
const fail_on = manifest.policy?.fail_on ?? DEFAULT_FAIL_ON;
|
|
66
|
+
const maxGov = manifest.policy?.max_governance_risk;
|
|
67
|
+
const minConf = manifest.policy?.min_decision_confidence;
|
|
68
|
+
const { industry, revenue_eur } = manifest.organization;
|
|
69
|
+
const results = manifest.initiatives.map((init) => {
|
|
70
|
+
const r = score({
|
|
71
|
+
industry,
|
|
72
|
+
revenue_eur,
|
|
73
|
+
function: init.function,
|
|
74
|
+
ai_tier: init.ai_tier,
|
|
75
|
+
readiness: init.readiness,
|
|
76
|
+
scores: init.scores,
|
|
77
|
+
signal_completeness: init.signal_completeness,
|
|
78
|
+
});
|
|
79
|
+
const violations = [];
|
|
80
|
+
if (fail_on.includes(r.classification)) {
|
|
81
|
+
violations.push(`classification ${r.classification} is blocked by policy.fail_on`);
|
|
82
|
+
}
|
|
83
|
+
if (typeof maxGov === 'number' && init.scores.governance_risk > maxGov) {
|
|
84
|
+
violations.push(`governance_risk ${init.scores.governance_risk} exceeds max_governance_risk ${maxGov}`);
|
|
85
|
+
}
|
|
86
|
+
if (typeof minConf === 'number' && r.confidence < minConf) {
|
|
87
|
+
violations.push(`decision_confidence ${r.confidence} below min_decision_confidence ${minConf}`);
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
id: init.id,
|
|
91
|
+
function: init.function,
|
|
92
|
+
ai_tier: init.ai_tier,
|
|
93
|
+
classification: r.classification,
|
|
94
|
+
decision_confidence: r.confidence,
|
|
95
|
+
governance_risk: init.scores.governance_risk,
|
|
96
|
+
net_value_eur: { low: r.net_low_eur, high: r.net_high_eur },
|
|
97
|
+
reason: r.reason,
|
|
98
|
+
...(r.caveat ? { caveat: r.caveat } : {}),
|
|
99
|
+
violations,
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
const failures = results.flatMap((res) => res.violations.map((v) => `${res.id}: ${v}`));
|
|
103
|
+
return {
|
|
104
|
+
ok: failures.length === 0,
|
|
105
|
+
policy: { fail_on, max_governance_risk: maxGov, min_decision_confidence: minConf },
|
|
106
|
+
results,
|
|
107
|
+
failures,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { runCheck, lintManifest } from './index.js';
|
|
4
|
+
const baseManifest = {
|
|
5
|
+
bvf_version: '1.0',
|
|
6
|
+
organization: { industry: 'financial', revenue_eur: 400_000_000 },
|
|
7
|
+
policy: { fail_on: ['Stop'], max_governance_risk: 60, min_decision_confidence: 50 },
|
|
8
|
+
initiatives: [
|
|
9
|
+
{
|
|
10
|
+
id: 'cx-genai-bot', function: 'cx', ai_tier: 'gen2', readiness: 'traditional',
|
|
11
|
+
scores: { strategic_alignment: 70, financial_return: 50, change_enablement: 55, governance_risk: 45 },
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
test('a healthy initiative passes the gate', () => {
|
|
16
|
+
const r = runCheck(baseManifest);
|
|
17
|
+
assert.equal(r.ok, true);
|
|
18
|
+
assert.equal(r.failures.length, 0);
|
|
19
|
+
assert.equal(r.results[0].violations.length, 0);
|
|
20
|
+
});
|
|
21
|
+
test('a Stop initiative fails on fail_on', () => {
|
|
22
|
+
const m = {
|
|
23
|
+
...baseManifest,
|
|
24
|
+
initiatives: [{
|
|
25
|
+
id: 'doomed', function: 'finance', ai_tier: 'gen1', readiness: 'siloed',
|
|
26
|
+
// governance_risk 75 → score() returns Stop
|
|
27
|
+
scores: { strategic_alignment: 30, financial_return: 15, change_enablement: 20, governance_risk: 75 },
|
|
28
|
+
}],
|
|
29
|
+
};
|
|
30
|
+
const r = runCheck(m);
|
|
31
|
+
assert.equal(r.ok, false);
|
|
32
|
+
assert.equal(r.results[0].classification, 'Stop');
|
|
33
|
+
assert.ok(r.failures.some((f) => f.includes('Stop')));
|
|
34
|
+
});
|
|
35
|
+
test('max_governance_risk ceiling is enforced independently of classification', () => {
|
|
36
|
+
const m = {
|
|
37
|
+
...baseManifest,
|
|
38
|
+
policy: { fail_on: [], max_governance_risk: 40 },
|
|
39
|
+
initiatives: [{
|
|
40
|
+
id: 'risky', function: 'cx', ai_tier: 'gen2', readiness: 'traditional',
|
|
41
|
+
scores: { strategic_alignment: 80, financial_return: 80, change_enablement: 80, governance_risk: 55 },
|
|
42
|
+
}],
|
|
43
|
+
};
|
|
44
|
+
const r = runCheck(m);
|
|
45
|
+
assert.equal(r.ok, false);
|
|
46
|
+
assert.ok(r.failures.some((f) => f.includes('governance_risk 55 exceeds')));
|
|
47
|
+
});
|
|
48
|
+
test('min_decision_confidence floor catches low-confidence verdicts', () => {
|
|
49
|
+
const m = {
|
|
50
|
+
...baseManifest,
|
|
51
|
+
policy: { fail_on: [], min_decision_confidence: 60 },
|
|
52
|
+
initiatives: [{
|
|
53
|
+
id: 'soft', function: 'cx', ai_tier: 'gen2', readiness: 'traditional',
|
|
54
|
+
scores: { strategic_alignment: 70, financial_return: 50, change_enablement: 55, governance_risk: 45 },
|
|
55
|
+
signal_completeness: 0.4, // haircuts confidence below 60
|
|
56
|
+
}],
|
|
57
|
+
};
|
|
58
|
+
const r = runCheck(m);
|
|
59
|
+
assert.equal(r.ok, false);
|
|
60
|
+
assert.ok(r.failures.some((f) => f.includes('below min_decision_confidence')));
|
|
61
|
+
assert.ok(r.results[0].caveat, 'low signal_completeness should surface a caveat');
|
|
62
|
+
});
|
|
63
|
+
test('policy defaults to fail_on Stop when omitted', () => {
|
|
64
|
+
const m = {
|
|
65
|
+
organization: { industry: 'retail', revenue_eur: 100_000_000 },
|
|
66
|
+
initiatives: [{
|
|
67
|
+
id: 'ok', function: 'sales', ai_tier: 'gen2', readiness: 'agile',
|
|
68
|
+
scores: { strategic_alignment: 75, financial_return: 70, change_enablement: 70, governance_risk: 20 },
|
|
69
|
+
}],
|
|
70
|
+
};
|
|
71
|
+
const r = runCheck(m);
|
|
72
|
+
assert.deepEqual(r.policy.fail_on, ['Stop']);
|
|
73
|
+
assert.equal(r.ok, true);
|
|
74
|
+
});
|
|
75
|
+
test('failures aggregate across multiple initiatives, ids preserved', () => {
|
|
76
|
+
const m = {
|
|
77
|
+
...baseManifest,
|
|
78
|
+
policy: { fail_on: ['Stop'], max_governance_risk: 50 },
|
|
79
|
+
initiatives: [
|
|
80
|
+
{ id: 'good', function: 'cx', ai_tier: 'gen2', readiness: 'agile',
|
|
81
|
+
scores: { strategic_alignment: 80, financial_return: 75, change_enablement: 70, governance_risk: 25 } },
|
|
82
|
+
{ id: 'bad', function: 'finance', ai_tier: 'gen1', readiness: 'siloed',
|
|
83
|
+
scores: { strategic_alignment: 30, financial_return: 15, change_enablement: 20, governance_risk: 80 } },
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
const r = runCheck(m);
|
|
87
|
+
assert.equal(r.ok, false);
|
|
88
|
+
assert.ok(r.failures.every((f) => f.startsWith('good:') || f.startsWith('bad:')));
|
|
89
|
+
assert.ok(r.failures.some((f) => f.startsWith('bad:')));
|
|
90
|
+
});
|
|
91
|
+
test('lintManifest catches structural gaps', () => {
|
|
92
|
+
assert.ok(lintManifest({}).length > 0);
|
|
93
|
+
assert.ok(lintManifest({ organization: { industry: 'retail', revenue_eur: 1 }, initiatives: [] }).length > 0);
|
|
94
|
+
assert.equal(lintManifest(baseManifest).length, 0);
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aibvf-check",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SonarQube for AI initiatives — a CI/CD pre-flight gate that fails the build when an AI initiative would not survive a board review. Deterministic, runs on AI BVF v1.0.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-bvf", "bvf", "ci", "ci-cd", "pre-flight", "gate", "ai-governance",
|
|
7
|
+
"ai-roi", "policy", "eu-ai-act", "github-action", "sonarqube-for-ai"
|
|
8
|
+
],
|
|
9
|
+
"homepage": "https://www.aibvf.com/protocol",
|
|
10
|
+
"repository": "github:Bahamas1717/ai-bvf",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "Craig Horton",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "dist/index.js",
|
|
15
|
+
"bin": {
|
|
16
|
+
"aibvf-check": "dist/cli.js"
|
|
17
|
+
},
|
|
18
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc && node -e \"require('fs').chmodSync('dist/cli.js', 0o755)\"",
|
|
21
|
+
"test": "node --test dist/*.test.js"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@aibvf/core": "^0.3.4"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"typescript": "^5.4.0",
|
|
28
|
+
"@types/node": "^20.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|