@transitrix/diagrams 1.13.3 → 1.14.0-rc.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/compliance/canon-catalog.js +1 -1
- package/dist/compliance/classify.d.ts +4 -1
- package/dist/compliance/classify.js +21 -1
- package/dist/compliance/index.d.ts +3 -0
- package/dist/compliance/index.js +1 -0
- package/dist/compliance/requirement-chain.d.ts +111 -0
- package/dist/compliance/requirement-chain.js +501 -0
- package/dist/compliance/reverse-index.js +4 -0
- package/dist/compliance/types.d.ts +20 -0
- package/package.json +1 -1
- package/src/compliance/canon-catalog.ts +1 -1
- package/src/compliance/classify.ts +24 -1
- package/src/compliance/index.ts +3 -0
- package/src/compliance/requirement-chain.ts +430 -0
- package/src/compliance/reverse-index.ts +3 -0
- package/src/compliance/types.ts +21 -0
|
@@ -44,7 +44,7 @@ export function buildComplianceScan(docs) {
|
|
|
44
44
|
const catalogMap = new Map();
|
|
45
45
|
const pathById = new Map();
|
|
46
46
|
for (const { path, data } of docs) {
|
|
47
|
-
const ingested = ingestComplianceDoc(complianceCanon, data);
|
|
47
|
+
const ingested = ingestComplianceDoc(complianceCanon, data, path);
|
|
48
48
|
if (ingested)
|
|
49
49
|
pathById.set(ingested, path);
|
|
50
50
|
const admitted = admitDocumentToCatalog(catalogMap, data);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChainRecord, ChainFinding } from './types.js';
|
|
1
2
|
import type { IndexAssertion, IndexRequirement, IndexVerification, IndexNeed, IndexValidation } from './types.js';
|
|
2
3
|
export interface ComplianceProduct {
|
|
3
4
|
id: string;
|
|
@@ -11,6 +12,8 @@ export interface ComplianceCodexDoc {
|
|
|
11
12
|
}
|
|
12
13
|
/** The bucketed result of scanning a repo for compliance canon. */
|
|
13
14
|
export interface ComplianceCanon {
|
|
15
|
+
records: ChainRecord[];
|
|
16
|
+
findings: ChainFinding[];
|
|
14
17
|
products: ComplianceProduct[];
|
|
15
18
|
requirements: IndexRequirement[];
|
|
16
19
|
assertions: IndexAssertion[];
|
|
@@ -49,4 +52,4 @@ export declare function emptyCanon(): ComplianceCanon;
|
|
|
49
52
|
* its id duplicates one already ingested into the same bucket (see
|
|
50
53
|
* `canon.duplicateIds`).
|
|
51
54
|
*/
|
|
52
|
-
export declare function ingestComplianceDoc(canon: ComplianceCanon, doc: unknown): string | null;
|
|
55
|
+
export declare function ingestComplianceDoc(canon: ComplianceCanon, doc: unknown, sourcePath?: string): string | null;
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
// for "what is a compliance artefact" — used by both the Studio extension scan
|
|
3
3
|
// (webview previews) and the CLI scan (`export-compliance`), so the recognition
|
|
4
4
|
// rules live once. Pure: takes a parsed YAML document, no IO.
|
|
5
|
+
import { typeOfId } from '../typed-id.js';
|
|
5
6
|
export function emptyCanon() {
|
|
6
7
|
return {
|
|
8
|
+
records: [],
|
|
9
|
+
findings: [],
|
|
7
10
|
products: [],
|
|
8
11
|
requirements: [],
|
|
9
12
|
assertions: [],
|
|
@@ -40,7 +43,8 @@ function pushUnique(canon, list, item) {
|
|
|
40
43
|
* its id duplicates one already ingested into the same bucket (see
|
|
41
44
|
* `canon.duplicateIds`).
|
|
42
45
|
*/
|
|
43
|
-
export function ingestComplianceDoc(canon, doc) {
|
|
46
|
+
export function ingestComplianceDoc(canon, doc, sourcePath = '') {
|
|
47
|
+
retainChainRecord(canon, doc, sourcePath);
|
|
44
48
|
if (doc === null || typeof doc !== 'object' || Array.isArray(doc))
|
|
45
49
|
return null;
|
|
46
50
|
const d = doc;
|
|
@@ -128,3 +132,19 @@ export function ingestComplianceDoc(canon, doc) {
|
|
|
128
132
|
}
|
|
129
133
|
return null;
|
|
130
134
|
}
|
|
135
|
+
/** Retain malformed values and cross-type duplicates without changing legacy buckets. */
|
|
136
|
+
function retainChainRecord(canon, doc, sourcePath) {
|
|
137
|
+
if (!doc || typeof doc !== 'object' || Array.isArray(doc)) {
|
|
138
|
+
canon.findings.push({ id: `${sourcePath}:document`, owner: sourcePath, field: '',
|
|
139
|
+
code: 'INTAKE', message: 'Expected a document mapping', reference: false, severity: 'error' });
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const raw = structuredClone(doc);
|
|
143
|
+
if (typeof raw.id !== 'string' || !raw.id.trim()) {
|
|
144
|
+
if ('id' in raw || 'zone' in raw || ['requirement', 'verification', 'need', 'product', 'release', 'relation', 'driver'].includes(String(raw.notation)))
|
|
145
|
+
canon.findings.push({ id: `${sourcePath}:id`, owner: sourcePath,
|
|
146
|
+
field: 'id', code: 'INTAKE', message: 'Missing record identity', reference: false, severity: 'error' });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
canon.records.push({ id: raw.id, type: typeOfId(raw.id) ?? '', sourcePath, raw });
|
|
150
|
+
}
|
|
@@ -19,3 +19,6 @@ export { assertionToScoringElement, complianceConfidenceHeader, requirementToSco
|
|
|
19
19
|
export { parseCoverageMetricConfig, buildCoverageMatrix, collectCoverageViewResolutionFindings, } from './coverage-metric.js';
|
|
20
20
|
export type { CoverageMetricConfig, CoverageMetricRegimes, CoverageMetricRegimesFilter, CoverageMetricSubjects, CoverageMetricThresholds, CoverageMatrix, CoverageRow, CoverageViewFinding, ParseCoverageMetricResult, RagStatus, } from './coverage-metric.js';
|
|
21
21
|
export type { ComplianceIndex, ComplianceIndexInput, DeadlineStatus, IndexRequirement, IndexAssertion, IndexVerification, IndexNeed, IndexValidation, LawTree, LawTreeRequirement, ProductView, ProductRequirementStatus, ObjectDetailDef, ObjectDetailInput, RequirementTrace, TraceAssertionRow, TraceVerificationRow, TraceElementCatalog, TraceElementRef, TraceSourceRef, } from './types.js';
|
|
22
|
+
export { buildRequirementChain, requirementReleaseCounts, selectRequirementChain, RequirementChainSnapshot, CHAIN_STAGES, chainDate } from './requirement-chain.js';
|
|
23
|
+
export type { ChainInput, ChainScope, ChainSet, RequirementChainNode, RequirementChainEdge, RequirementChainProjection } from './requirement-chain.js';
|
|
24
|
+
export type { ChainRecord, ChainFinding } from './types.js';
|
package/dist/compliance/index.js
CHANGED
|
@@ -11,3 +11,4 @@ export { renderComplianceHtml, renderImpactMatrixHtml } from './html.js';
|
|
|
11
11
|
export { buildImpactMatrix, renderImpactMarkdown, parseImpactViewConfig, collectImpactViewResolutionFindings, COMPLIANCE_IMPACT_DEFAULTS, extractObjectDetails, extractProcessFlowTasks, mergeStageTaskDetails, computeDeadlineStatus } from './impact.js';
|
|
12
12
|
export { assertionToScoringElement, complianceConfidenceHeader, requirementToScoringElement, scoreComplianceView, } from './confidence.js';
|
|
13
13
|
export { parseCoverageMetricConfig, buildCoverageMatrix, collectCoverageViewResolutionFindings, } from './coverage-metric.js';
|
|
14
|
+
export { buildRequirementChain, requirementReleaseCounts, selectRequirementChain, RequirementChainSnapshot, CHAIN_STAGES, chainDate } from './requirement-chain.js';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ChainRecord, ChainFinding, ComplianceIndex } from './types.js';
|
|
2
|
+
export declare const CHAIN_STAGES: readonly ["Source document", "Driver", "Need", "Stakeholder requirement", "System requirement", "Software requirement", "Unclassified requirement", "Verification definition", "Result"];
|
|
3
|
+
export interface ChainScope {
|
|
4
|
+
catalogue: string;
|
|
5
|
+
product?: string;
|
|
6
|
+
release?: string;
|
|
7
|
+
project?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ChainInput {
|
|
10
|
+
index: ComplianceIndex;
|
|
11
|
+
scope: ChainScope;
|
|
12
|
+
asAt: string;
|
|
13
|
+
snapshotId: string;
|
|
14
|
+
sourceRevision?: string;
|
|
15
|
+
complete: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ChainSet {
|
|
18
|
+
ids: string[];
|
|
19
|
+
completeness: 'complete' | 'incomplete';
|
|
20
|
+
total: number | null;
|
|
21
|
+
}
|
|
22
|
+
export interface RequirementChainNode {
|
|
23
|
+
id: string;
|
|
24
|
+
recordId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
stage: number;
|
|
27
|
+
sourcePath: string;
|
|
28
|
+
context: string[];
|
|
29
|
+
raw: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
export interface RequirementChainEdge {
|
|
32
|
+
id: string;
|
|
33
|
+
kind: string;
|
|
34
|
+
storedFrom: string;
|
|
35
|
+
storedTo: string;
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
identities: string[];
|
|
39
|
+
trace: boolean;
|
|
40
|
+
valid: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface ChainAssignment {
|
|
43
|
+
requirement: string;
|
|
44
|
+
nearest: string;
|
|
45
|
+
depth: number;
|
|
46
|
+
relations: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface RequirementChainProjection {
|
|
49
|
+
contract: 'requirement-chain/0.2';
|
|
50
|
+
contractRevision: string;
|
|
51
|
+
asAt: string;
|
|
52
|
+
snapshotId: string;
|
|
53
|
+
sourceRevision?: string;
|
|
54
|
+
scope: ChainScope;
|
|
55
|
+
completeness: 'complete' | 'incomplete';
|
|
56
|
+
scopeFindings: string[];
|
|
57
|
+
populations: {
|
|
58
|
+
product: ChainSet;
|
|
59
|
+
release: ChainSet;
|
|
60
|
+
selected: ChainSet;
|
|
61
|
+
inactive: ChainSet;
|
|
62
|
+
unresolved: ChainSet;
|
|
63
|
+
};
|
|
64
|
+
assignments: {
|
|
65
|
+
here: ChainSet;
|
|
66
|
+
otherReleaseOnly: ChainSet;
|
|
67
|
+
unassigned: ChainSet;
|
|
68
|
+
invalid: ChainSet;
|
|
69
|
+
provenance: ChainAssignment[];
|
|
70
|
+
};
|
|
71
|
+
stages: ChainSet[];
|
|
72
|
+
metrics: {
|
|
73
|
+
broken: ChainSet;
|
|
74
|
+
noSource: ChainSet;
|
|
75
|
+
noDefinition: ChainSet;
|
|
76
|
+
noResult: ChainSet;
|
|
77
|
+
failed: ChainSet;
|
|
78
|
+
unassigned: ChainSet;
|
|
79
|
+
};
|
|
80
|
+
records: ChainRecord[];
|
|
81
|
+
nodes: RequirementChainNode[];
|
|
82
|
+
edges: RequirementChainEdge[];
|
|
83
|
+
findings: ChainFinding[];
|
|
84
|
+
defectiveReferences: ChainSet;
|
|
85
|
+
selectedReferences: ChainSet;
|
|
86
|
+
unattributableFindings: ChainSet;
|
|
87
|
+
affectedRequirements: Record<string, string[]>;
|
|
88
|
+
definitions: Record<string, string[]>;
|
|
89
|
+
executions: Record<string, string[]>;
|
|
90
|
+
}
|
|
91
|
+
export declare function chainDate(v: unknown): v is string;
|
|
92
|
+
/** Pure, lossless release projection; no legacy coverage verdict is reinterpreted. */
|
|
93
|
+
export declare function buildRequirementChain(input: ChainInput): RequirementChainProjection;
|
|
94
|
+
/** Both is two independent walks, never an expansion from the union frontier. */
|
|
95
|
+
export declare function selectRequirementChain(p: RequirementChainProjection, focus?: string, direction?: 'upstream' | 'downstream' | 'both'): {
|
|
96
|
+
nodes: RequirementChainNode[];
|
|
97
|
+
edges: RequirementChainEdge[];
|
|
98
|
+
};
|
|
99
|
+
/** Count/list contract for the release report, derived solely from the shared snapshot. */
|
|
100
|
+
export declare function requirementReleaseCounts(p: RequirementChainProjection): Record<string, {
|
|
101
|
+
label: string;
|
|
102
|
+
unit: "requirements" | "references" | "findings" | "source documents" | "drivers" | "needs" | "definition parts" | "result parts";
|
|
103
|
+
set: ChainSet;
|
|
104
|
+
}>;
|
|
105
|
+
/** Monotonic refresh gate shared by reports; late successes and failures cannot replace newer data. */
|
|
106
|
+
export declare class RequirementChainSnapshot {
|
|
107
|
+
private generation;
|
|
108
|
+
current?: RequirementChainProjection;
|
|
109
|
+
stale: boolean;
|
|
110
|
+
refresh(load: () => Promise<ChainInput>): Promise<boolean>;
|
|
111
|
+
}
|