specky-sdd 3.4.0 → 3.6.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/.apm/hooks/scripts/ears-validator.sh +56 -17
- package/.apm/prompts/specky-api.prompt.md +1 -1
- package/.apm/prompts/specky-research.prompt.md +2 -2
- package/.apm/skills/research-analyst/SKILL.md +2 -2
- package/.apm/skills/specky-onboarding/SKILL.md +6 -4
- package/CHANGELOG.md +58 -0
- package/README.md +39 -10
- package/SECURITY.md +15 -8
- package/apm.yml +1 -1
- package/config.yml +1 -1
- package/dist/cli/commands/serve.d.ts.map +1 -1
- package/dist/cli/commands/serve.js +3 -2
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +24 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +92 -6
- package/dist/config.js.map +1 -1
- package/dist/index.js +63 -14
- package/dist/index.js.map +1 -1
- package/dist/services/audit-logger.d.ts +54 -5
- package/dist/services/audit-logger.d.ts.map +1 -1
- package/dist/services/audit-logger.js +121 -9
- package/dist/services/audit-logger.js.map +1 -1
- package/dist/services/diagram-generator.d.ts +53 -4
- package/dist/services/diagram-generator.d.ts.map +1 -1
- package/dist/services/diagram-generator.js +565 -178
- package/dist/services/diagram-generator.js.map +1 -1
- package/dist/services/doc-generator.d.ts +44 -0
- package/dist/services/doc-generator.d.ts.map +1 -1
- package/dist/services/doc-generator.js +352 -50
- package/dist/services/doc-generator.js.map +1 -1
- package/dist/services/document-converter.d.ts +10 -7
- package/dist/services/document-converter.d.ts.map +1 -1
- package/dist/services/document-converter.js +113 -38
- package/dist/services/document-converter.js.map +1 -1
- package/dist/services/file-manager.d.ts.map +1 -1
- package/dist/services/file-manager.js +9 -3
- package/dist/services/file-manager.js.map +1 -1
- package/dist/services/iac-generator.d.ts +31 -3
- package/dist/services/iac-generator.d.ts.map +1 -1
- package/dist/services/iac-generator.js +509 -41
- package/dist/services/iac-generator.js.map +1 -1
- package/dist/services/pbt-generator.d.ts +12 -0
- package/dist/services/pbt-generator.d.ts.map +1 -1
- package/dist/services/pbt-generator.js +296 -145
- package/dist/services/pbt-generator.js.map +1 -1
- package/dist/services/state-machine.d.ts +15 -1
- package/dist/services/state-machine.d.ts.map +1 -1
- package/dist/services/state-machine.js +21 -3
- package/dist/services/state-machine.js.map +1 -1
- package/dist/services/test-generator.d.ts +8 -0
- package/dist/services/test-generator.d.ts.map +1 -1
- package/dist/services/test-generator.js +134 -33
- package/dist/services/test-generator.js.map +1 -1
- package/dist/services/test-traceability-mapper.d.ts.map +1 -1
- package/dist/services/test-traceability-mapper.js +8 -3
- package/dist/services/test-traceability-mapper.js.map +1 -1
- package/dist/services/work-item-exporter.d.ts +70 -9
- package/dist/services/work-item-exporter.d.ts.map +1 -1
- package/dist/services/work-item-exporter.js +115 -53
- package/dist/services/work-item-exporter.js.map +1 -1
- package/dist/templates/checklist.md +2 -3
- package/dist/templates/cross-analysis.md +2 -4
- package/dist/tools/audit.js +1 -1
- package/dist/tools/audit.js.map +1 -1
- package/dist/tools/documentation.d.ts.map +1 -1
- package/dist/tools/documentation.js +9 -3
- package/dist/tools/documentation.js.map +1 -1
- package/dist/tools/environment.d.ts.map +1 -1
- package/dist/tools/environment.js +75 -12
- package/dist/tools/environment.js.map +1 -1
- package/dist/tools/infrastructure.d.ts.map +1 -1
- package/dist/tools/infrastructure.js +7 -39
- package/dist/tools/infrastructure.js.map +1 -1
- package/dist/tools/input.js +4 -4
- package/dist/tools/input.js.map +1 -1
- package/dist/tools/integration.js +4 -4
- package/dist/tools/integration.js.map +1 -1
- package/dist/tools/pipeline.d.ts.map +1 -1
- package/dist/tools/pipeline.js +42 -4
- package/dist/tools/pipeline.js.map +1 -1
- package/dist/tools/quality.d.ts.map +1 -1
- package/dist/tools/quality.js +36 -9
- package/dist/tools/quality.js.map +1 -1
- package/dist/tools/rbac.d.ts.map +1 -1
- package/dist/tools/rbac.js +18 -11
- package/dist/tools/rbac.js.map +1 -1
- package/dist/tools/testing.d.ts +10 -0
- package/dist/tools/testing.d.ts.map +1 -1
- package/dist/tools/testing.js +66 -13
- package/dist/tools/testing.js.map +1 -1
- package/dist/tools/tool-enforcement.d.ts +15 -1
- package/dist/tools/tool-enforcement.d.ts.map +1 -1
- package/dist/tools/tool-enforcement.js +70 -9
- package/dist/tools/tool-enforcement.js.map +1 -1
- package/dist/tools/transcript.d.ts.map +1 -1
- package/dist/tools/transcript.js +66 -41
- package/dist/tools/transcript.js.map +1 -1
- package/dist/tools/utility.d.ts.map +1 -1
- package/dist/tools/utility.js +22 -12
- package/dist/tools/utility.js.map +1 -1
- package/dist/tools/visualization.d.ts +21 -0
- package/dist/tools/visualization.d.ts.map +1 -1
- package/dist/tools/visualization.js +130 -29
- package/dist/tools/visualization.js.map +1 -1
- package/dist/utils/token-table.d.ts +41 -0
- package/dist/utils/token-table.d.ts.map +1 -0
- package/dist/utils/token-table.js +103 -0
- package/dist/utils/token-table.js.map +1 -0
- package/package.json +1 -1
- package/templates/checklist.md +2 -3
- package/templates/cross-analysis.md +2 -4
|
@@ -6,29 +6,92 @@
|
|
|
6
6
|
* - Hash-chaining: each entry includes SHA-256 hash of the previous entry line
|
|
7
7
|
* - Log rotation: when file exceeds max_file_size_mb, rotates to .audit.jsonl.1
|
|
8
8
|
* - Export formats: jsonl (default), syslog (RFC 5424), otlp (stub)
|
|
9
|
+
*
|
|
10
|
+
* v3.5.0 enterprise enhancements (all opt-in):
|
|
11
|
+
* - Tamper evidence: when an HMAC key is provided (SDD_AUDIT_HMAC_KEY or
|
|
12
|
+
* SDD_AUDIT_HMAC_KEY_FILE — held OUTSIDE the workspace), every entry is
|
|
13
|
+
* signed with HMAC-SHA256 over its serialized form (which includes
|
|
14
|
+
* previous_hash, chaining the signatures). A workspace-writing attacker
|
|
15
|
+
* can recompute the plain hash chain but cannot forge HMACs without the
|
|
16
|
+
* key. Truncation of the log tail is NOT detectable by the chain alone —
|
|
17
|
+
* anchor `current_hash` externally (e.g. in CI logs) to close that gap.
|
|
18
|
+
* - Fail-closed: when enabled, a failed audit write throws instead of being
|
|
19
|
+
* swallowed, so the enforcement layer can refuse to run unaudited tools.
|
|
9
20
|
*/
|
|
10
21
|
import { appendFile, mkdir, stat, rename, unlink, readFile } from "node:fs/promises";
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
11
23
|
import { join, dirname } from "node:path";
|
|
12
|
-
import { createHash } from "node:crypto";
|
|
24
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
13
25
|
/** Seed value for the first entry's previous_hash field */
|
|
14
26
|
const CHAIN_SEED = "specky-audit-v1";
|
|
15
27
|
/** Max rotated log files to keep */
|
|
16
28
|
const MAX_ROTATIONS = 3;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the audit HMAC key from the environment: SDD_AUDIT_HMAC_KEY wins,
|
|
31
|
+
* else SDD_AUDIT_HMAC_KEY_FILE is read (trimmed). Returns "" when unset so the
|
|
32
|
+
* feature stays off. The key file should live OUTSIDE the workspace with 0600
|
|
33
|
+
* permissions — a key readable/writable from the workspace defeats the purpose.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveAuditHmacKey(env = process.env) {
|
|
36
|
+
const direct = env["SDD_AUDIT_HMAC_KEY"];
|
|
37
|
+
if (direct && direct.trim())
|
|
38
|
+
return direct.trim();
|
|
39
|
+
const keyFile = env["SDD_AUDIT_HMAC_KEY_FILE"];
|
|
40
|
+
if (keyFile && keyFile.trim()) {
|
|
41
|
+
try {
|
|
42
|
+
const key = readFileSync(keyFile.trim(), "utf-8").trim();
|
|
43
|
+
if (key)
|
|
44
|
+
return key;
|
|
45
|
+
console.error(`[specky] Audit HMAC key file is empty: ${keyFile}`);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error(`[specky] Cannot read SDD_AUDIT_HMAC_KEY_FILE (${keyFile}): ${err.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
/** HMAC-SHA256 over the serialized entry (without its hmac field). */
|
|
54
|
+
function signLine(baseLine, key) {
|
|
55
|
+
return createHmac("sha256", key).update(baseLine).digest("hex");
|
|
56
|
+
}
|
|
57
|
+
function constantTimeEqualHex(a, b) {
|
|
58
|
+
const bufA = Buffer.from(a);
|
|
59
|
+
const bufB = Buffer.from(b);
|
|
60
|
+
return bufA.length === bufB.length && timingSafeEqual(bufA, bufB);
|
|
61
|
+
}
|
|
17
62
|
export class AuditLogger {
|
|
18
63
|
workspaceRoot;
|
|
19
64
|
enabled;
|
|
65
|
+
lastHash = CHAIN_SEED;
|
|
20
66
|
exportFormat;
|
|
21
67
|
maxFileSizeMb;
|
|
22
|
-
|
|
23
|
-
|
|
68
|
+
hmacKey;
|
|
69
|
+
failClosed;
|
|
70
|
+
constructor(workspaceRoot, enabled, exportFormatOrOptions = {}, maxFileSizeMb = 10) {
|
|
24
71
|
this.workspaceRoot = workspaceRoot;
|
|
25
72
|
this.enabled = enabled;
|
|
26
|
-
|
|
27
|
-
|
|
73
|
+
// Back-compat: the pre-3.5 signature was (root, enabled, exportFormat, maxFileSizeMb).
|
|
74
|
+
const options = typeof exportFormatOrOptions === "string"
|
|
75
|
+
? { exportFormat: exportFormatOrOptions, maxFileSizeMb }
|
|
76
|
+
: exportFormatOrOptions;
|
|
77
|
+
this.exportFormat = options.exportFormat ?? "jsonl";
|
|
78
|
+
this.maxFileSizeMb = options.maxFileSizeMb ?? 10;
|
|
79
|
+
this.hmacKey = options.hmacKey ?? "";
|
|
80
|
+
this.failClosed = options.failClosed ?? false;
|
|
81
|
+
}
|
|
82
|
+
/** True when entries are signed (an HMAC key is configured). */
|
|
83
|
+
get isTamperEvident() {
|
|
84
|
+
return this.hmacKey.length > 0;
|
|
85
|
+
}
|
|
86
|
+
/** True when audit-write failures propagate instead of being swallowed. */
|
|
87
|
+
get isFailClosed() {
|
|
88
|
+
return this.failClosed;
|
|
28
89
|
}
|
|
29
90
|
/**
|
|
30
91
|
* Log a tool call to the audit file.
|
|
31
|
-
* No-ops when disabled.
|
|
92
|
+
* No-ops when disabled. By default never throws — audit failures must not
|
|
93
|
+
* break tool calls. In fail-closed mode the error propagates so the
|
|
94
|
+
* enforcement wrapper can refuse to execute unaudited work.
|
|
32
95
|
*/
|
|
33
96
|
async log(entry) {
|
|
34
97
|
if (!this.enabled)
|
|
@@ -39,7 +102,15 @@ export class AuditLogger {
|
|
|
39
102
|
// Rotate if needed before appending
|
|
40
103
|
await this.rotateIfNeeded(auditFile);
|
|
41
104
|
entry.previous_hash = await this.readCurrentChainHash(auditFile);
|
|
42
|
-
|
|
105
|
+
// Serialize without hmac, sign, then append the signature as the final
|
|
106
|
+
// field by string surgery — verification can strip it back off without
|
|
107
|
+
// depending on JSON key-order round-trips.
|
|
108
|
+
delete entry.hmac;
|
|
109
|
+
const baseLine = JSON.stringify(entry);
|
|
110
|
+
const signedLine = this.hmacKey
|
|
111
|
+
? `${baseLine.slice(0, -1)},"hmac":"${signLine(baseLine, this.hmacKey)}"}`
|
|
112
|
+
: baseLine;
|
|
113
|
+
const line = signedLine + "\n";
|
|
43
114
|
if (this.exportFormat === "syslog") {
|
|
44
115
|
await this.appendSyslog(auditFile, entry, line);
|
|
45
116
|
}
|
|
@@ -53,7 +124,11 @@ export class AuditLogger {
|
|
|
53
124
|
// Advance chain: hash of the line just written
|
|
54
125
|
this.lastHash = createHash("sha256").update(line.trimEnd()).digest("hex");
|
|
55
126
|
}
|
|
56
|
-
catch {
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (this.failClosed) {
|
|
129
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
130
|
+
throw new Error(`Audit write failed (fail-closed mode): ${message}`);
|
|
131
|
+
}
|
|
57
132
|
// Audit failures must never break the tool call — silently ignore
|
|
58
133
|
}
|
|
59
134
|
}
|
|
@@ -90,15 +165,22 @@ export class AuditLogger {
|
|
|
90
165
|
resetChain() {
|
|
91
166
|
this.lastHash = CHAIN_SEED;
|
|
92
167
|
}
|
|
93
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* Verify audit integrity for an audit file: always checks the previous_hash
|
|
170
|
+
* chain; additionally verifies HMAC signatures when a key is configured.
|
|
171
|
+
* With the key, a rewritten/reordered log is detected even if the attacker
|
|
172
|
+
* recomputed the plain hash chain.
|
|
173
|
+
*/
|
|
94
174
|
async verifyChain(specDir) {
|
|
95
175
|
const auditFile = this.resolveAuditFile(specDir);
|
|
176
|
+
const hmacChecked = this.hmacKey.length > 0;
|
|
96
177
|
try {
|
|
97
178
|
const raw = await readFile(auditFile, "utf-8");
|
|
98
179
|
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
99
180
|
const errors = [];
|
|
100
181
|
let expectedPreviousHash = CHAIN_SEED;
|
|
101
182
|
let currentHash = CHAIN_SEED;
|
|
183
|
+
let signedEntries = 0;
|
|
102
184
|
for (let index = 0; index < lines.length; index++) {
|
|
103
185
|
const line = lines[index];
|
|
104
186
|
let entry;
|
|
@@ -113,6 +195,13 @@ export class AuditLogger {
|
|
|
113
195
|
if (entry.previous_hash !== expectedPreviousHash) {
|
|
114
196
|
errors.push(`Line ${index + 1}: previous_hash mismatch`);
|
|
115
197
|
}
|
|
198
|
+
if (typeof entry.hmac === "string")
|
|
199
|
+
signedEntries++;
|
|
200
|
+
if (hmacChecked) {
|
|
201
|
+
const hmacError = this.verifyLineHmac(line, entry, index + 1);
|
|
202
|
+
if (hmacError)
|
|
203
|
+
errors.push(hmacError);
|
|
204
|
+
}
|
|
116
205
|
currentHash = createHash("sha256").update(line).digest("hex");
|
|
117
206
|
expectedPreviousHash = currentHash;
|
|
118
207
|
}
|
|
@@ -122,6 +211,8 @@ export class AuditLogger {
|
|
|
122
211
|
total_entries: lines.length,
|
|
123
212
|
current_hash: currentHash,
|
|
124
213
|
errors,
|
|
214
|
+
hmac_checked: hmacChecked,
|
|
215
|
+
signed_entries: signedEntries,
|
|
125
216
|
};
|
|
126
217
|
}
|
|
127
218
|
catch {
|
|
@@ -131,9 +222,30 @@ export class AuditLogger {
|
|
|
131
222
|
total_entries: 0,
|
|
132
223
|
current_hash: CHAIN_SEED,
|
|
133
224
|
errors: [],
|
|
225
|
+
hmac_checked: hmacChecked,
|
|
226
|
+
signed_entries: 0,
|
|
134
227
|
};
|
|
135
228
|
}
|
|
136
229
|
}
|
|
230
|
+
/** Check one line's HMAC. Returns an error string or null when valid. */
|
|
231
|
+
verifyLineHmac(line, entry, lineNumber) {
|
|
232
|
+
if (typeof entry.hmac !== "string") {
|
|
233
|
+
return `Line ${lineNumber}: missing hmac (entry written without the signing key)`;
|
|
234
|
+
}
|
|
235
|
+
// The writer appends `,"hmac":"<hex>"}` as the final field; strip it to
|
|
236
|
+
// recover the exact signed serialization.
|
|
237
|
+
const marker = `,"hmac":"`;
|
|
238
|
+
const markerIndex = line.lastIndexOf(marker);
|
|
239
|
+
if (markerIndex === -1 || !line.endsWith(`"}`)) {
|
|
240
|
+
return `Line ${lineNumber}: hmac field is not in canonical position`;
|
|
241
|
+
}
|
|
242
|
+
const baseLine = line.slice(0, markerIndex) + "}";
|
|
243
|
+
const expected = signLine(baseLine, this.hmacKey);
|
|
244
|
+
if (!constantTimeEqualHex(entry.hmac, expected)) {
|
|
245
|
+
return `Line ${lineNumber}: hmac mismatch (entry modified or signed with a different key)`;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
137
249
|
resolveAuditFile(specDir, _featureNumber) {
|
|
138
250
|
return join(this.workspaceRoot, specDir, ".audit.jsonl");
|
|
139
251
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/services/audit-logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"audit-logger.js","sourceRoot":"","sources":["../../src/services/audit-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DiagramGenerator — Deterministic Mermaid diagram generation from spec artifacts.
|
|
3
3
|
* All generation is pure string manipulation — no AI calls.
|
|
4
|
+
*
|
|
5
|
+
* Invariants:
|
|
6
|
+
* - Every identifier position (node ids, entity names, class names, state ids,
|
|
7
|
+
* participants) contains only [A-Za-z0-9_]; human text lives in quoted labels.
|
|
8
|
+
* - No generator emits constant filler: output is derived from the artifact's
|
|
9
|
+
* requirements, sections, bullets, or (as a last resort) its title/words, so
|
|
10
|
+
* different inputs never produce byte-identical diagrams.
|
|
11
|
+
* - Numeric values (pie slices, gantt tasks) are real counts from the source,
|
|
12
|
+
* never fabricated percentages.
|
|
4
13
|
*/
|
|
5
14
|
import type { FileManager } from "./file-manager.js";
|
|
6
15
|
import type { DiagramSpec, AllDiagramsResult, DiagramType } from "../types.js";
|
|
@@ -12,9 +21,13 @@ export declare class DiagramGenerator {
|
|
|
12
21
|
*/
|
|
13
22
|
generateDiagram(content: string, type: DiagramType, title: string): DiagramSpec;
|
|
14
23
|
/**
|
|
15
|
-
* Generate ALL diagram types for a feature from its artifacts
|
|
24
|
+
* Generate ALL diagram types for a feature from its artifacts and write the
|
|
25
|
+
* full set to DIAGRAMS.md in the feature directory (grouped by source),
|
|
26
|
+
* replacing any scaffold left by earlier pipeline steps.
|
|
16
27
|
*/
|
|
17
|
-
generateAllDiagrams(specDir: string, featureDir: string): Promise<AllDiagramsResult
|
|
28
|
+
generateAllDiagrams(specDir: string, featureDir: string): Promise<AllDiagramsResult & {
|
|
29
|
+
diagrams_file: string | null;
|
|
30
|
+
}>;
|
|
18
31
|
/**
|
|
19
32
|
* Generate user story flow diagram.
|
|
20
33
|
*/
|
|
@@ -38,16 +51,52 @@ export declare class DiagramGenerator {
|
|
|
38
51
|
private generateNetworkTopology;
|
|
39
52
|
private extractListItems;
|
|
40
53
|
private extractActors;
|
|
41
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Derive request/response exchanges from EARS requirement sentences.
|
|
56
|
+
* "When X, the system shall Y" -> Client request "X", System response "Y".
|
|
57
|
+
*/
|
|
58
|
+
private extractRequirementExchanges;
|
|
42
59
|
private extractEntities;
|
|
43
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Class/interface candidates for class and c4_code diagrams.
|
|
62
|
+
* 1. Explicit `interface X { ... }` / `class X { ... }` declarations (methods
|
|
63
|
+
* read from the real body — never invented).
|
|
64
|
+
* 2. Real section names with methods derived from their bullet items.
|
|
65
|
+
* 3. Last resort: one class built from the artifact's opening words, so
|
|
66
|
+
* different artifacts never collapse to an identical stub.
|
|
67
|
+
*/
|
|
68
|
+
private extractClassCandidates;
|
|
44
69
|
private extractStates;
|
|
45
70
|
private extractSystems;
|
|
46
71
|
private extractComponents;
|
|
47
72
|
private extractTasks;
|
|
73
|
+
/**
|
|
74
|
+
* Real category counts for pie charts, tried in order:
|
|
75
|
+
* 1. Explicit EARS pattern tags, e.g. "(EVENT_DRIVEN)".
|
|
76
|
+
* 2. Classification of "shall" requirement sentences by EARS keyword.
|
|
77
|
+
* 3. REQ-ID prefixes (### REQ-XXX-NNN).
|
|
78
|
+
* 4. Section names weighted by their real bullet counts.
|
|
79
|
+
*/
|
|
48
80
|
private extractCategories;
|
|
49
81
|
private extractTopics;
|
|
82
|
+
/**
|
|
83
|
+
* Real (non-structural) sections with their bullet items — the shared
|
|
84
|
+
* source-derived skeleton used by fallback paths.
|
|
85
|
+
*/
|
|
86
|
+
private extractSections;
|
|
50
87
|
private sanitize;
|
|
88
|
+
/** Text safe outside quotes (gantt names/sections, message-free positions). */
|
|
89
|
+
private plainText;
|
|
90
|
+
/** Sequence message text — keeps it on one line and free of ':' markers. */
|
|
91
|
+
private messageText;
|
|
92
|
+
/** Identifier containing only [A-Za-z0-9_], never starting with a digit. */
|
|
93
|
+
private safeId;
|
|
94
|
+
private uniqueId;
|
|
95
|
+
private cleanHeading;
|
|
96
|
+
private toPascalCase;
|
|
97
|
+
private toCamelCase;
|
|
98
|
+
private isStructuralHeading;
|
|
99
|
+
private buildDiagramsMarkdown;
|
|
51
100
|
private safeRead;
|
|
52
101
|
}
|
|
53
102
|
//# sourceMappingURL=diagram-generator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-generator.d.ts","sourceRoot":"","sources":["../../src/services/diagram-generator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"diagram-generator.d.ts","sourceRoot":"","sources":["../../src/services/diagram-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkB/E,qBAAa,gBAAgB;IACf,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,WAAW;IAE5C;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW;IA8D/E;;;;OAIG;IACG,mBAAmB,CACvB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,GAAG;QAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IA2DhE;;OAEG;IACH,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;IAclE,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,WAAW;IA8BnB,OAAO,CAAC,oBAAoB;IA6B5B,OAAO,CAAC,oBAAoB;IAqC5B,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,mBAAmB;IAyB3B,OAAO,CAAC,aAAa;IAwDrB,OAAO,CAAC,WAAW;IA6BnB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,gBAAgB;IA6BxB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,WAAW;IAkCnB,OAAO,CAAC,kBAAkB;IAoC1B,OAAO,CAAC,uBAAuB;IA+C/B,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;IAgBrB;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IA2BnC,OAAO,CAAC,eAAe;IAavB;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IAgD9B,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,YAAY;IAmBpB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAoDzB,OAAO,CAAC,aAAa;IAoBrB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,QAAQ;IAIhB,+EAA+E;IAC/E,OAAO,CAAC,SAAS;IAIjB,4EAA4E;IAC5E,OAAO,CAAC,WAAW;IAKnB,4EAA4E;IAC5E,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,qBAAqB;YAqCf,QAAQ;CAOvB"}
|