@transitrix/diagrams 1.13.2 → 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/activities/types.d.ts +5 -0
- 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/dist/fgca/parse-canonical.js +1 -0
- package/dist/fgca/preview-layout.d.ts +1 -0
- package/dist/fgca/preview-layout.js +1 -1
- package/dist/fgca/types.d.ts +2 -0
- package/dist/webview/completion-percent.d.ts +10 -0
- package/dist/webview/completion-percent.js +12 -0
- package/dist/webview/render-activities.js +2 -0
- package/dist/webview/render-fgca.d.ts +0 -14
- package/dist/webview/render-fgca.js +3 -15
- package/package.json +4 -4
- package/src/activities/types.ts +2 -0
- 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
- package/src/fgca/parse-canonical.ts +1 -0
- package/src/fgca/preview-layout.ts +2 -1
- package/src/fgca/types.ts +2 -0
- package/src/webview/completion-percent.ts +18 -0
- package/src/webview/render-activities.ts +2 -0
- package/src/webview/render-fgca.ts +3 -15
package/src/compliance/types.ts
CHANGED
|
@@ -176,6 +176,8 @@ export interface ObjectDetailInput {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
export interface ComplianceIndexInput {
|
|
179
|
+
records?: ChainRecord[];
|
|
180
|
+
findings?: ChainFinding[];
|
|
179
181
|
requirements: IndexRequirement[];
|
|
180
182
|
assertions: IndexAssertion[];
|
|
181
183
|
/** Optional — absent inputs (existing callers) simply index no verifications. */
|
|
@@ -188,6 +190,8 @@ export interface ComplianceIndexInput {
|
|
|
188
190
|
|
|
189
191
|
/** The reverse-index — all maps are keyed by canonical id. */
|
|
190
192
|
export interface ComplianceIndex {
|
|
193
|
+
recordsById: Map<string, ChainRecord[]>;
|
|
194
|
+
findings: ChainFinding[];
|
|
191
195
|
requirementById: Map<string, IndexRequirement>;
|
|
192
196
|
/** Codex artefact id → requirements whose `derived_from` names it. */
|
|
193
197
|
requirementsByLaw: Map<string, IndexRequirement[]>;
|
|
@@ -313,3 +317,20 @@ export interface TraceElementCatalog {
|
|
|
313
317
|
/** id → human-readable name (or the id itself when unnamed). */
|
|
314
318
|
nameById: Map<string, string>;
|
|
315
319
|
}
|
|
320
|
+
|
|
321
|
+
/** Lossless records retained beside the compatible legacy projections. */
|
|
322
|
+
export interface ChainRecord {
|
|
323
|
+
id: string;
|
|
324
|
+
type: string;
|
|
325
|
+
sourcePath: string;
|
|
326
|
+
raw: Record<string, unknown>;
|
|
327
|
+
}
|
|
328
|
+
export interface ChainFinding {
|
|
329
|
+
id: string;
|
|
330
|
+
owner: string;
|
|
331
|
+
field: string;
|
|
332
|
+
code: string;
|
|
333
|
+
message: string;
|
|
334
|
+
reference: boolean;
|
|
335
|
+
severity: 'error' | 'warning';
|
|
336
|
+
}
|
|
@@ -332,6 +332,7 @@ export function parseCanonicalFGCA(
|
|
|
332
332
|
name: String(el!['name'] ?? ''),
|
|
333
333
|
goal_id: goalRefs.length > 0 ? goalRefs[0] : null,
|
|
334
334
|
...(typeVal !== undefined ? { type: typeVal } : {}),
|
|
335
|
+
...(typeof el!['link'] === 'string' ? { link: el!['link'] } : {}),
|
|
335
336
|
...(progressVal !== undefined ? { progress: progressVal } : {}),
|
|
336
337
|
};
|
|
337
338
|
});
|
|
@@ -30,6 +30,7 @@ export interface FGCAPreviewChange {
|
|
|
30
30
|
activity_ids: Array<number | string>;
|
|
31
31
|
}
|
|
32
32
|
export interface FGCAPreviewActivity {
|
|
33
|
+
link?: string;
|
|
33
34
|
id: number | string;
|
|
34
35
|
name: string;
|
|
35
36
|
goal_id?: number | string | null;
|
|
@@ -387,7 +388,7 @@ export function layoutFGCAPreview(
|
|
|
387
388
|
...changes.map(c => ({ id: `change_${c.id}`, label: c.name })),
|
|
388
389
|
...virtualChanges.map(v => ({ id: v.id, label: '–', virtual: true })),
|
|
389
390
|
],
|
|
390
|
-
activity: doc.activities.map(a => ({ id: `activity_${a.id}`, label: a.name, progress: a.progress, linked: a.
|
|
391
|
+
activity: doc.activities.map(a => ({ id: `activity_${a.id}`, label: a.name, progress: a.progress, linked: Boolean(a.link?.trim()) })),
|
|
391
392
|
};
|
|
392
393
|
|
|
393
394
|
// Build predecessor map: for each node, which node IDs in the previous column
|
package/src/fgca/types.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface ActivityItem {
|
|
|
25
25
|
activity_type_id?: number;
|
|
26
26
|
/** Canonical values: initiative | programme | project | work_package. Unknown values pass through without error. */
|
|
27
27
|
type?: string;
|
|
28
|
+
/** Tracker link, independent of goal relationships. */
|
|
29
|
+
link?: string;
|
|
28
30
|
progress?: {
|
|
29
31
|
percent: number;
|
|
30
32
|
computedAt: string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Shared completion display contract for Action, DGA and DGCA previews. */
|
|
2
|
+
export interface ActionProgress {
|
|
3
|
+
percent: number;
|
|
4
|
+
computedAt: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function completionPercentState(progress: ActionProgress | undefined, linked: boolean, enabled = true, now = Date.now()): { label: string; stale: boolean } | undefined {
|
|
8
|
+
if (!enabled) return undefined;
|
|
9
|
+
if (progress && Number.isFinite(progress.percent) && progress.percent >= 0 && progress.percent <= 100 && Number.isFinite(Date.parse(progress.computedAt))) {
|
|
10
|
+
return { label: `${progress.percent}%`, stale: now - Date.parse(progress.computedAt) > 7 * 24 * 60 * 60 * 1000 };
|
|
11
|
+
}
|
|
12
|
+
return linked ? { label: '–%', stale: false } : undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function completionPercentSvg(progress: ActionProgress | undefined, linked: boolean, x: number, y: number, enabled = true): string {
|
|
16
|
+
const state = completionPercentState(progress, linked, enabled);
|
|
17
|
+
return state ? `<text class="text-id completion-percent" x="${x}" y="${y}" text-anchor="end" dominant-baseline="hanging" font-size="10"${state.stale ? ' opacity="0.5"' : ''}>${state.label}</text>` : '';
|
|
18
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* in `renderActivitiesNetworkBody` and is shared verbatim with the VS Code
|
|
17
17
|
* preview's `networkSvg`.
|
|
18
18
|
*/
|
|
19
|
+
import { completionPercentSvg } from './completion-percent.js';
|
|
19
20
|
import { layoutActivities } from '../activities/layout.js';
|
|
20
21
|
import { computeCpm } from '../activities/cpm.js';
|
|
21
22
|
import type {
|
|
@@ -147,6 +148,7 @@ function activityNodeSvg(
|
|
|
147
148
|
return [
|
|
148
149
|
`<rect class="${cls}" x="${x}" y="${y}" width="${n.width}" height="${n.height}" rx="8"/>`,
|
|
149
150
|
textSvg,
|
|
151
|
+
completionPercentSvg(n.data.progress, Boolean(n.data.link?.trim()), x + n.width - 8, y + 6),
|
|
150
152
|
durLabel ? `<text class="text-secondary" x="${x + n.width - 8}" y="${y + n.height - 8}" text-anchor="end">${durLabel}</text>` : '',
|
|
151
153
|
].filter(Boolean).join('\n');
|
|
152
154
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* `change` column (`hideChanges` / the layout's Goal → Activity collapse),
|
|
13
13
|
* exactly as the extension preview does.
|
|
14
14
|
*/
|
|
15
|
+
import { completionPercentSvg } from './completion-percent.js';
|
|
15
16
|
import {
|
|
16
17
|
layoutFGCAPreview,
|
|
17
18
|
FGCA_NODE_W,
|
|
@@ -65,7 +66,6 @@ export function renderFgcaBody(
|
|
|
65
66
|
const edgeStyle = bodyOptions.edgeStyle;
|
|
66
67
|
const showCompletionPercent = bodyOptions.showCompletionPercent ?? true;
|
|
67
68
|
const headerTruncate = Math.max(8, Math.floor((nodeWidth - 16) / 7));
|
|
68
|
-
const STALENESS_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
|
|
69
69
|
|
|
70
70
|
const headerSvg = columns
|
|
71
71
|
.map(({ col, x }) =>
|
|
@@ -103,20 +103,8 @@ export function renderFgcaBody(
|
|
|
103
103
|
const typeBadge = n.type && n.col === 'activity'
|
|
104
104
|
? `<text class="text-id" x="${n.x + nodeWidth - 6}" y="${n.y + 10}" text-anchor="end" dominant-baseline="hanging" font-size="10">${escXml(n.type)}</text>`
|
|
105
105
|
: '';
|
|
106
|
-
const progressBadge =
|
|
107
|
-
? (()
|
|
108
|
-
if (n.progress) {
|
|
109
|
-
const computedAt = new Date(n.progress.computedAt);
|
|
110
|
-
const now = new Date();
|
|
111
|
-
const isStale = now.getTime() - computedAt.getTime() > STALENESS_THRESHOLD_MS;
|
|
112
|
-
const opacity = isStale ? ' opacity="0.5"' : '';
|
|
113
|
-
return `<text class="text-id" x="${n.x + nodeWidth - 6}" y="${n.y + 22}" text-anchor="end" dominant-baseline="hanging" font-size="10"${opacity}>${escXml(n.progress.percent + '%')}</text>`;
|
|
114
|
-
}
|
|
115
|
-
if (n.linked) {
|
|
116
|
-
return `<text class="text-id" x="${n.x + nodeWidth - 6}" y="${n.y + 22}" text-anchor="end" dominant-baseline="hanging" font-size="10">–%</text>`;
|
|
117
|
-
}
|
|
118
|
-
return '';
|
|
119
|
-
})()
|
|
106
|
+
const progressBadge = n.col === 'activity'
|
|
107
|
+
? completionPercentSvg(n.progress, Boolean(n.linked), n.x + nodeWidth - 6, n.y + 22, showCompletionPercent)
|
|
120
108
|
: '';
|
|
121
109
|
return [
|
|
122
110
|
`<g>`,
|