@sigloch/graphcode-client 0.4.0 → 0.5.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/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/readiness-completeness.d.ts +29 -24
- package/dist/readiness-completeness.js +27 -43
- package/dist/readiness.js +2 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -19,5 +19,5 @@
|
|
|
19
19
|
export { HOST_SOCK_BASENAME, callHost, type ShimRequest, type ShimResponse, } from './host-client.js';
|
|
20
20
|
export { MARKDOWN_VIEWS, VIEW_FILENAMES, type MarkdownView } from './view-catalog.js';
|
|
21
21
|
export { GRAPHCODE_INCOSE_SCOPE, PHASE_GATE_RULES, PHASE_GATE_LABELS, PHASE_GATE_CREATIONS, IMPL_GATE_PHASE, IMPL_GATE_MILESTONES, IMPL_GATE_RULES, ABSENT_CREATION_PROVIDER, creationBlockingMsg, summarizeReadiness, computeReadiness, scoreReadiness, getFamilyRuleIds, type IncoseScope, type CreationCurrency, type CreationCurrencyProvider, type ReadinessDimension, type ReadinessGate, type ReadinessReport, } from './readiness.js';
|
|
22
|
-
export { NEUTRAL_COMPLETENESS, COMPLETENESS_SLICES, scoreCompleteness, typeOf,
|
|
22
|
+
export { NEUTRAL_COMPLETENESS, COMPLETENESS_SLICES, scoreCompleteness, typeOf, type CGraph, type CNode, type GateCompleteness, type CompletenessLeg, } from './readiness-completeness.js';
|
|
23
23
|
export * from './panels.js';
|
package/dist/index.js
CHANGED
|
@@ -19,5 +19,5 @@
|
|
|
19
19
|
export { HOST_SOCK_BASENAME, callHost, } from './host-client.js';
|
|
20
20
|
export { MARKDOWN_VIEWS, VIEW_FILENAMES } from './view-catalog.js';
|
|
21
21
|
export { GRAPHCODE_INCOSE_SCOPE, PHASE_GATE_RULES, PHASE_GATE_LABELS, PHASE_GATE_CREATIONS, IMPL_GATE_PHASE, IMPL_GATE_MILESTONES, IMPL_GATE_RULES, ABSENT_CREATION_PROVIDER, creationBlockingMsg, summarizeReadiness, computeReadiness, scoreReadiness, getFamilyRuleIds, } from './readiness.js';
|
|
22
|
-
export { NEUTRAL_COMPLETENESS, COMPLETENESS_SLICES, scoreCompleteness, typeOf,
|
|
22
|
+
export { NEUTRAL_COMPLETENESS, COMPLETENESS_SLICES, scoreCompleteness, typeOf, } from './readiness-completeness.js';
|
|
23
23
|
export * from './panels.js';
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* readiness-completeness.ts — the COMPLETENESS dimension of readiness (CR-GC-250,
|
|
3
|
-
* split out of readiness.ts by CR-GC-260).
|
|
3
|
+
* split out of readiness.ts by CR-GC-260; rebuilt on the rule stream CR-SM-226).
|
|
4
4
|
*
|
|
5
5
|
* Its own module because it answers a different question than the rest of readiness:
|
|
6
6
|
* compliance/gates ask "does any element violate a rule", completeness asks "is the
|
|
7
7
|
* structural chain covered at all" — the absence case rules cannot see (0 FCHAIN → a
|
|
8
8
|
* per-element warning rule fires 0 times and the gate reads green).
|
|
9
9
|
*
|
|
10
|
+
* CR-SM-226: every leg now reads off a named `@sigloch/contracts` rule instead of
|
|
11
|
+
* re-walking the graph locally. The former local out-edge/actor-boundary/testRef/
|
|
12
|
+
* codeRef/leaf-function helpers were a SECOND, drifting implementation of exactly
|
|
13
|
+
* what R-15/UC-01/UC-03/FC-04/SC-04/R-19/R-20 already check in `@sigloch/contracts/se`
|
|
14
|
+
* — deleted. The rule engine stays the single source of truth; this file only
|
|
15
|
+
* re-groups its violations by the DRIVING population per leg, so an EMPTY
|
|
16
|
+
* population still counts against the gate (the vacuous-complete case a
|
|
17
|
+
* per-element warning rule cannot see on its own — closed for real by
|
|
18
|
+
* `@sigloch/contracts/se`'s R-28 Ebenen-Präsenz, CR-SM-226).
|
|
19
|
+
*
|
|
10
20
|
* BROWSER-SAFE — no `node:*` import may enter this file: the panels layer builds on it.
|
|
11
21
|
*
|
|
12
22
|
* @author andreas@siglochconsulting
|
|
13
23
|
*/
|
|
14
24
|
import type { Graph } from '@sigloch/graph-api-core';
|
|
25
|
+
import type { RuleViolation } from '@sigloch/contracts/harness';
|
|
15
26
|
export type CGraph = Pick<Graph, 'nodes' | 'edges'>;
|
|
16
27
|
export type CNode = Graph['nodes'][number];
|
|
17
28
|
/** A gate's structural completeness over its driving population. */
|
|
@@ -25,40 +36,34 @@ export interface GateCompleteness {
|
|
|
25
36
|
}
|
|
26
37
|
/** Neutral completeness for gates that carry no chain slice (impl gates). */
|
|
27
38
|
export declare const NEUTRAL_COMPLETENESS: GateCompleteness;
|
|
39
|
+
export declare const typeOf: (byId: Map<string, CNode>, id: string) => string | undefined;
|
|
28
40
|
/**
|
|
29
41
|
* One completeness leg: every node of `sourceType` (the driving population)
|
|
30
|
-
* must
|
|
31
|
-
*
|
|
32
|
-
*
|
|
42
|
+
* must carry NO violation of `ruleId` (its `@sigloch/contracts` rule twin),
|
|
43
|
+
* else it is a `missing` source for the owning gate. Cardinality legs use the
|
|
44
|
+
* id `"<SRC>→<TGT>"` so the drift test can match them against the
|
|
45
|
+
* meta-model's `1..*` patterns.
|
|
33
46
|
*/
|
|
34
47
|
export interface CompletenessLeg {
|
|
35
48
|
id: string;
|
|
36
49
|
sourceType: string;
|
|
37
|
-
|
|
50
|
+
ruleId: string;
|
|
38
51
|
}
|
|
39
|
-
export declare const typeOf: (byId: Map<string, CNode>, id: string) => string | undefined;
|
|
40
|
-
/** True iff `src` has ≥1 out-edge of `edgeType` to a node of `targetType`. */
|
|
41
|
-
export declare function hasOutTo(g: CGraph, byId: Map<string, CNode>, src: string, edgeType: string, targetType: string): boolean;
|
|
42
|
-
export declare const refFile: (ref: unknown) => string | undefined;
|
|
43
|
-
export declare const hasTestRef: (n: CNode) => boolean;
|
|
44
|
-
export declare const hasCodeRef: (n: CNode) => boolean;
|
|
45
|
-
/** A leaf FUNC has no `compose→FUNC` children (parents are realized by children — meta-model §28). */
|
|
46
|
-
export declare const isLeafFunc: (n: CNode, g: CGraph, byId: Map<string, CNode>) => boolean;
|
|
47
|
-
/**
|
|
48
|
-
* A FCHAIN is actor-bounded iff its function set has a trigger AND a consumer:
|
|
49
|
-
* `ACTOR —io→ FLOW —io→ FUNC∈chain` (entry) and `FUNC∈chain —io→ FLOW —io→ ACTOR`
|
|
50
|
-
* (exit). Catches the "hollow chain" — functions with no who-triggers / who-consumes.
|
|
51
|
-
*/
|
|
52
|
-
export declare function fchainActorBounded(fchain: CNode, g: CGraph, byId: Map<string, CNode>): boolean;
|
|
53
52
|
/**
|
|
54
|
-
* Phase-gate → chain legs that must be complete AT THAT PHASE
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
53
|
+
* Phase-gate → chain legs that must be complete AT THAT PHASE, each backed by
|
|
54
|
+
* its `@sigloch/contracts` rule twin (CR-SM-226):
|
|
55
|
+
* SRR: SYS→UC ≈ R-17 (SYS must have compose; not UC-typed specifically —
|
|
56
|
+
* no dedicated SYS→UC rule exists, R-17 is the closest twin),
|
|
57
|
+
* UC→FCHAIN = UC-03, UC→REQ = UC-01.
|
|
58
|
+
* PDR: FCHAIN→FUNC = R-15, FCHAIN-actor-bounded = FC-04 (trigger+consumer).
|
|
59
|
+
* CDR: FLOW→SCHEMA = SC-04 (sharp per-FLOW version of SC-02).
|
|
60
|
+
* TRR: TEST.testRef = R-19, FUNC.realRef = R-20.
|
|
58
61
|
*/
|
|
59
62
|
export declare const COMPLETENESS_SLICES: Record<string, CompletenessLeg[]>;
|
|
60
63
|
/**
|
|
61
64
|
* Score one phase gate's structural completeness over its driving population.
|
|
62
65
|
* `total === 0` (no source elements to cover) → vacuously complete (ratio 1).
|
|
66
|
+
* `violations` is the full rule-stream output (e.g. `harness.evaluateRules()`);
|
|
67
|
+
* only the leg's own `ruleId` is consulted per node.
|
|
63
68
|
*/
|
|
64
|
-
export declare function scoreCompleteness(gateId: string, graph: CGraph): GateCompleteness;
|
|
69
|
+
export declare function scoreCompleteness(gateId: string, graph: CGraph, violations: RuleViolation[]): GateCompleteness;
|
|
@@ -1,78 +1,62 @@
|
|
|
1
1
|
/** Neutral completeness for gates that carry no chain slice (impl gates). */
|
|
2
2
|
export const NEUTRAL_COMPLETENESS = { covered: 0, total: 0, missing: [] };
|
|
3
3
|
export const typeOf = (byId, id) => byId.get(id)?.type;
|
|
4
|
-
/** True iff `src` has ≥1 out-edge of `edgeType` to a node of `targetType`. */
|
|
5
|
-
export function hasOutTo(g, byId, src, edgeType, targetType) {
|
|
6
|
-
return g.edges.some((e) => e.sourceId === src && e.edgeType === edgeType && typeOf(byId, e.targetId) === targetType);
|
|
7
|
-
}
|
|
8
|
-
export const refFile = (ref) => ref?.file;
|
|
9
|
-
export const hasTestRef = (n) => !!refFile(n.attributes?.testRef);
|
|
10
|
-
export const hasCodeRef = (n) => !!refFile(n.attributes?.realRef);
|
|
11
|
-
/** A leaf FUNC has no `compose→FUNC` children (parents are realized by children — meta-model §28). */
|
|
12
|
-
export const isLeafFunc = (n, g, byId) => !hasOutTo(g, byId, n.uid, 'compose', 'FUNC');
|
|
13
|
-
/**
|
|
14
|
-
* A FCHAIN is actor-bounded iff its function set has a trigger AND a consumer:
|
|
15
|
-
* `ACTOR —io→ FLOW —io→ FUNC∈chain` (entry) and `FUNC∈chain —io→ FLOW —io→ ACTOR`
|
|
16
|
-
* (exit). Catches the "hollow chain" — functions with no who-triggers / who-consumes.
|
|
17
|
-
*/
|
|
18
|
-
export function fchainActorBounded(fchain, g, byId) {
|
|
19
|
-
const funcs = new Set(g.edges.filter((e) => e.sourceId === fchain.uid && e.edgeType === 'compose' && typeOf(byId, e.targetId) === 'FUNC').map((e) => e.targetId));
|
|
20
|
-
if (funcs.size === 0)
|
|
21
|
-
return false;
|
|
22
|
-
const io = g.edges.filter((e) => e.edgeType === 'io');
|
|
23
|
-
const entry = io.some((e) => funcs.has(e.targetId) && typeOf(byId, e.sourceId) === 'FLOW' &&
|
|
24
|
-
io.some((a) => a.targetId === e.sourceId && typeOf(byId, a.sourceId) === 'ACTOR'));
|
|
25
|
-
const exit = io.some((e) => funcs.has(e.sourceId) && typeOf(byId, e.targetId) === 'FLOW' &&
|
|
26
|
-
io.some((a) => a.sourceId === e.targetId && typeOf(byId, a.targetId) === 'ACTOR'));
|
|
27
|
-
return entry && exit;
|
|
28
|
-
}
|
|
29
4
|
/**
|
|
30
|
-
* Phase-gate → chain legs that must be complete AT THAT PHASE
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
5
|
+
* Phase-gate → chain legs that must be complete AT THAT PHASE, each backed by
|
|
6
|
+
* its `@sigloch/contracts` rule twin (CR-SM-226):
|
|
7
|
+
* SRR: SYS→UC ≈ R-17 (SYS must have compose; not UC-typed specifically —
|
|
8
|
+
* no dedicated SYS→UC rule exists, R-17 is the closest twin),
|
|
9
|
+
* UC→FCHAIN = UC-03, UC→REQ = UC-01.
|
|
10
|
+
* PDR: FCHAIN→FUNC = R-15, FCHAIN-actor-bounded = FC-04 (trigger+consumer).
|
|
11
|
+
* CDR: FLOW→SCHEMA = SC-04 (sharp per-FLOW version of SC-02).
|
|
12
|
+
* TRR: TEST.testRef = R-19, FUNC.realRef = R-20.
|
|
34
13
|
*/
|
|
35
14
|
export const COMPLETENESS_SLICES = {
|
|
36
15
|
// Behavioral spine exists: system has use cases, every UC derives a chain AND requirements.
|
|
37
16
|
SRR: [
|
|
38
|
-
{ id: 'SYS→UC', sourceType: 'SYS',
|
|
39
|
-
{ id: 'UC→FCHAIN', sourceType: 'UC',
|
|
40
|
-
{ id: 'UC→REQ', sourceType: 'UC',
|
|
17
|
+
{ id: 'SYS→UC', sourceType: 'SYS', ruleId: 'R-17' },
|
|
18
|
+
{ id: 'UC→FCHAIN', sourceType: 'UC', ruleId: 'UC-03' },
|
|
19
|
+
{ id: 'UC→REQ', sourceType: 'UC', ruleId: 'UC-01' },
|
|
41
20
|
],
|
|
42
21
|
// Functional architecture: every chain has functions AND is actor-bounded (trigger + consumer).
|
|
43
22
|
PDR: [
|
|
44
|
-
{ id: 'FCHAIN→FUNC', sourceType: 'FCHAIN',
|
|
45
|
-
{ id: 'FCHAIN-actor-bounded', sourceType: 'FCHAIN',
|
|
23
|
+
{ id: 'FCHAIN→FUNC', sourceType: 'FCHAIN', ruleId: 'R-15' },
|
|
24
|
+
{ id: 'FCHAIN-actor-bounded', sourceType: 'FCHAIN', ruleId: 'FC-04' },
|
|
46
25
|
],
|
|
47
26
|
// Interfaces carry a data contract: every FLOW has a SCHEMA (CR-GC-106 schema-before-code).
|
|
48
27
|
CDR: [
|
|
49
|
-
{ id: 'FLOW→SCHEMA', sourceType: 'FLOW',
|
|
28
|
+
{ id: 'FLOW→SCHEMA', sourceType: 'FLOW', ruleId: 'SC-04' },
|
|
50
29
|
],
|
|
51
|
-
// Binding: tests are runnable and
|
|
30
|
+
// Binding: tests are runnable and functions carry code — concept/external exemptions
|
|
31
|
+
// are R-19/R-20's own business now (single source of truth), not re-decided here.
|
|
52
32
|
TRR: [
|
|
53
|
-
{ id: 'TEST.testRef', sourceType: 'TEST',
|
|
54
|
-
{ id: 'FUNC.realRef', sourceType: 'FUNC',
|
|
33
|
+
{ id: 'TEST.testRef', sourceType: 'TEST', ruleId: 'R-19' },
|
|
34
|
+
{ id: 'FUNC.realRef', sourceType: 'FUNC', ruleId: 'R-20' },
|
|
55
35
|
],
|
|
56
36
|
};
|
|
57
37
|
/**
|
|
58
38
|
* Score one phase gate's structural completeness over its driving population.
|
|
59
39
|
* `total === 0` (no source elements to cover) → vacuously complete (ratio 1).
|
|
40
|
+
* `violations` is the full rule-stream output (e.g. `harness.evaluateRules()`);
|
|
41
|
+
* only the leg's own `ruleId` is consulted per node.
|
|
60
42
|
*/
|
|
61
|
-
export function scoreCompleteness(gateId, graph) {
|
|
43
|
+
export function scoreCompleteness(gateId, graph, violations) {
|
|
62
44
|
const legs = COMPLETENESS_SLICES[gateId] ?? [];
|
|
63
|
-
const byId = new Map(graph.nodes.map((n) => [n.uid, n]));
|
|
64
45
|
let covered = 0;
|
|
65
46
|
let total = 0;
|
|
66
47
|
const missing = [];
|
|
67
48
|
for (const leg of legs) {
|
|
49
|
+
const violatingIds = new Set(violations
|
|
50
|
+
.filter((v) => v.ruleId === leg.ruleId && v.elementId !== undefined)
|
|
51
|
+
.map((v) => v.elementId));
|
|
68
52
|
for (const node of graph.nodes) {
|
|
69
53
|
if (node.type !== leg.sourceType)
|
|
70
54
|
continue;
|
|
71
55
|
total += 1;
|
|
72
|
-
if (
|
|
73
|
-
covered += 1;
|
|
74
|
-
else
|
|
56
|
+
if (violatingIds.has(node.uid))
|
|
75
57
|
missing.push(`${leg.id}: ${node.uid}`);
|
|
58
|
+
else
|
|
59
|
+
covered += 1;
|
|
76
60
|
}
|
|
77
61
|
}
|
|
78
62
|
return { covered, total, missing };
|
package/dist/readiness.js
CHANGED
|
@@ -142,7 +142,8 @@ function scorePhaseGate(id, ruleIds, violations, creations, graph, currency) {
|
|
|
142
142
|
? creations.filter((c) => currency(c) !== 'current').map((c) => creationBlockingMsg(c, id))
|
|
143
143
|
: [];
|
|
144
144
|
// Structural completeness (CR-GC-250): one aggregated blocking line, not N warnings.
|
|
145
|
-
|
|
145
|
+
// CR-SM-226: reads off the SAME violations array (the rule stream), no re-walk.
|
|
146
|
+
const completeness = scoreCompleteness(id, graph, violations);
|
|
146
147
|
const complete = completeness.covered === completeness.total;
|
|
147
148
|
const completenessBlocking = complete
|
|
148
149
|
? []
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigloch/graphcode-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"prepublishOnly": "npm run build && npm run test"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@sigloch/contracts": "^
|
|
20
|
+
"@sigloch/contracts": "^3.0.0",
|
|
21
21
|
"@sigloch/graph-api-core": "^2.0.0"
|
|
22
22
|
},
|
|
23
23
|
"license": "MIT",
|