guardian-framework 0.1.132 → 0.1.134
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/cli.js
CHANGED
|
@@ -3078,7 +3078,11 @@ function categorizeFile(relativePath) {
|
|
|
3078
3078
|
"agent/AGENTS.md",
|
|
3079
3079
|
"domain/",
|
|
3080
3080
|
"architecture/CHANGELOG.md",
|
|
3081
|
-
"architecture/implementation-roadmap.md"
|
|
3081
|
+
"architecture/implementation-roadmap.md",
|
|
3082
|
+
"architecture/diagrams/",
|
|
3083
|
+
"architecture/modules/",
|
|
3084
|
+
"architecture/decisions/",
|
|
3085
|
+
"architecture/contracts/"
|
|
3082
3086
|
];
|
|
3083
3087
|
if (userEditable.some((p3) => relativePath.includes(p3))) {
|
|
3084
3088
|
return "user";
|
|
@@ -3202,7 +3206,7 @@ __export(exports_package, {
|
|
|
3202
3206
|
bin: () => bin,
|
|
3203
3207
|
author: () => author
|
|
3204
3208
|
});
|
|
3205
|
-
var name = "guardian-framework", version = "0.1.
|
|
3209
|
+
var name = "guardian-framework", version = "0.1.134", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
|
|
3206
3210
|
var init_package = __esm(() => {
|
|
3207
3211
|
exports = {
|
|
3208
3212
|
".": {
|
|
@@ -11085,6 +11089,12 @@ async function runUpdate(targetDir, options) {
|
|
|
11085
11089
|
outro(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
11086
11090
|
}
|
|
11087
11091
|
}
|
|
11092
|
+
function isUserOwnedPiPath(manifestPath) {
|
|
11093
|
+
const p3 = manifestPath.replace(/^\.pi\//, "").toLowerCase();
|
|
11094
|
+
if (p3.includes("template"))
|
|
11095
|
+
return false;
|
|
11096
|
+
return p3.startsWith("architecture/diagrams/") || p3.startsWith("architecture/modules/") || p3.startsWith("architecture/decisions/") || p3.startsWith("architecture/contracts/") || p3.startsWith("architecture/architecture-overview.md") || p3.startsWith("domain/exploration.md") || p3.startsWith("domain/exploration/") || p3.startsWith("domain/ubiquitous-language.md");
|
|
11097
|
+
}
|
|
11088
11098
|
function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
11089
11099
|
const changes = [];
|
|
11090
11100
|
const templatePaths = new Set(templateFiles);
|
|
@@ -11092,6 +11102,14 @@ function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
|
11092
11102
|
if (!filePath.startsWith(".pi/"))
|
|
11093
11103
|
continue;
|
|
11094
11104
|
const fullPath = path9.join(targetDir, filePath);
|
|
11105
|
+
if (isUserOwnedPiPath(filePath)) {
|
|
11106
|
+
changes.push({
|
|
11107
|
+
path: filePath,
|
|
11108
|
+
action: "preserve",
|
|
11109
|
+
reason: "Project-owned architecture content \u2014 never overwritten by update"
|
|
11110
|
+
});
|
|
11111
|
+
continue;
|
|
11112
|
+
}
|
|
11095
11113
|
if (!templatePaths.has(filePath.replace(".pi/", ""))) {
|
|
11096
11114
|
changes.push({
|
|
11097
11115
|
path: filePath,
|
|
@@ -11148,6 +11166,15 @@ function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
|
11148
11166
|
for (const relativePath of templateFiles) {
|
|
11149
11167
|
const manifestPath = `.pi/${relativePath}`;
|
|
11150
11168
|
if (!manifest.files[manifestPath]) {
|
|
11169
|
+
const existing = path9.join(targetDir, manifestPath);
|
|
11170
|
+
if (fs10.existsSync(existing) && isUserOwnedPiPath(manifestPath)) {
|
|
11171
|
+
changes.push({
|
|
11172
|
+
path: manifestPath,
|
|
11173
|
+
action: "preserve",
|
|
11174
|
+
reason: "Project-owned content already exists"
|
|
11175
|
+
});
|
|
11176
|
+
continue;
|
|
11177
|
+
}
|
|
11151
11178
|
changes.push({ path: manifestPath, action: "add", reason: "New template file" });
|
|
11152
11179
|
}
|
|
11153
11180
|
}
|
|
@@ -12838,6 +12865,27 @@ ${bc.description}
|
|
|
12838
12865
|
}
|
|
12839
12866
|
content += `
|
|
12840
12867
|
`;
|
|
12868
|
+
content += `## Application Services (from exploration use-cases)
|
|
12869
|
+
`;
|
|
12870
|
+
content += `
|
|
12871
|
+
`;
|
|
12872
|
+
const ctxServices = (sessionResult.applicationServices ?? []).filter((svc) => svc.context === bc.name);
|
|
12873
|
+
if (ctxServices.length === 0) {
|
|
12874
|
+
content += `None captured in exploration yet (run the use-cases pass).
|
|
12875
|
+
|
|
12876
|
+
`;
|
|
12877
|
+
} else {
|
|
12878
|
+
content += `| Service | Use case | Maps to FR |
|
|
12879
|
+
`;
|
|
12880
|
+
content += `|---------|----------|-----------|
|
|
12881
|
+
`;
|
|
12882
|
+
for (const svc of ctxServices) {
|
|
12883
|
+
content += `| \`${svc.name}\` | ${svc.useCase ?? "\u2014"} | ${svc.mapsToFr ?? "\u2014"} |
|
|
12884
|
+
`;
|
|
12885
|
+
}
|
|
12886
|
+
content += `
|
|
12887
|
+
`;
|
|
12888
|
+
}
|
|
12841
12889
|
content += `## Ubiquitous Language
|
|
12842
12890
|
`;
|
|
12843
12891
|
content += `
|
package/dist/exports.js
CHANGED
|
@@ -1898,7 +1898,11 @@ function categorizeFile(relativePath) {
|
|
|
1898
1898
|
"agent/AGENTS.md",
|
|
1899
1899
|
"domain/",
|
|
1900
1900
|
"architecture/CHANGELOG.md",
|
|
1901
|
-
"architecture/implementation-roadmap.md"
|
|
1901
|
+
"architecture/implementation-roadmap.md",
|
|
1902
|
+
"architecture/diagrams/",
|
|
1903
|
+
"architecture/modules/",
|
|
1904
|
+
"architecture/decisions/",
|
|
1905
|
+
"architecture/contracts/"
|
|
1902
1906
|
];
|
|
1903
1907
|
if (userEditable.some((p2) => relativePath.includes(p2))) {
|
|
1904
1908
|
return "user";
|
|
@@ -1987,7 +1991,7 @@ __export(exports_package, {
|
|
|
1987
1991
|
bin: () => bin,
|
|
1988
1992
|
author: () => author
|
|
1989
1993
|
});
|
|
1990
|
-
var name = "guardian-framework", version = "0.1.
|
|
1994
|
+
var name = "guardian-framework", version = "0.1.134", description = "Token-optimized agentic framework scaffolder with pi-first architecture", type = "module", main = "dist/exports.js", exports, types = "dist/exports.d.ts", bin, files, engines, scripts, publishConfig, pi, repository, homepage = "https://github.com/arman-jalili/guardian-framework#readme", bugs, dependencies, devDependencies, keywords, author = "Arman Wolkensteiner-Jalili", license = "MIT", package_default;
|
|
1991
1995
|
var init_package = __esm(() => {
|
|
1992
1996
|
exports = {
|
|
1993
1997
|
".": {
|
|
@@ -10209,6 +10213,12 @@ async function runUpdate(targetDir, options) {
|
|
|
10209
10213
|
outro(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
10210
10214
|
}
|
|
10211
10215
|
}
|
|
10216
|
+
function isUserOwnedPiPath(manifestPath) {
|
|
10217
|
+
const p2 = manifestPath.replace(/^\.pi\//, "").toLowerCase();
|
|
10218
|
+
if (p2.includes("template"))
|
|
10219
|
+
return false;
|
|
10220
|
+
return p2.startsWith("architecture/diagrams/") || p2.startsWith("architecture/modules/") || p2.startsWith("architecture/decisions/") || p2.startsWith("architecture/contracts/") || p2.startsWith("architecture/architecture-overview.md") || p2.startsWith("domain/exploration.md") || p2.startsWith("domain/exploration/") || p2.startsWith("domain/ubiquitous-language.md");
|
|
10221
|
+
}
|
|
10212
10222
|
function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
10213
10223
|
const changes = [];
|
|
10214
10224
|
const templatePaths = new Set(templateFiles);
|
|
@@ -10216,6 +10226,14 @@ function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
|
10216
10226
|
if (!filePath.startsWith(".pi/"))
|
|
10217
10227
|
continue;
|
|
10218
10228
|
const fullPath = path5.join(targetDir, filePath);
|
|
10229
|
+
if (isUserOwnedPiPath(filePath)) {
|
|
10230
|
+
changes.push({
|
|
10231
|
+
path: filePath,
|
|
10232
|
+
action: "preserve",
|
|
10233
|
+
reason: "Project-owned architecture content — never overwritten by update"
|
|
10234
|
+
});
|
|
10235
|
+
continue;
|
|
10236
|
+
}
|
|
10219
10237
|
if (!templatePaths.has(filePath.replace(".pi/", ""))) {
|
|
10220
10238
|
changes.push({
|
|
10221
10239
|
path: filePath,
|
|
@@ -10272,6 +10290,15 @@ function analyzeChanges(targetDir, manifest, templateFiles, context, options) {
|
|
|
10272
10290
|
for (const relativePath of templateFiles) {
|
|
10273
10291
|
const manifestPath = `.pi/${relativePath}`;
|
|
10274
10292
|
if (!manifest.files[manifestPath]) {
|
|
10293
|
+
const existing = path5.join(targetDir, manifestPath);
|
|
10294
|
+
if (fs6.existsSync(existing) && isUserOwnedPiPath(manifestPath)) {
|
|
10295
|
+
changes.push({
|
|
10296
|
+
path: manifestPath,
|
|
10297
|
+
action: "preserve",
|
|
10298
|
+
reason: "Project-owned content already exists"
|
|
10299
|
+
});
|
|
10300
|
+
continue;
|
|
10301
|
+
}
|
|
10275
10302
|
changes.push({ path: manifestPath, action: "add", reason: "New template file" });
|
|
10276
10303
|
}
|
|
10277
10304
|
}
|
|
@@ -13162,6 +13189,27 @@ ${bc.description}
|
|
|
13162
13189
|
}
|
|
13163
13190
|
content += `
|
|
13164
13191
|
`;
|
|
13192
|
+
content += `## Application Services (from exploration use-cases)
|
|
13193
|
+
`;
|
|
13194
|
+
content += `
|
|
13195
|
+
`;
|
|
13196
|
+
const ctxServices = (sessionResult.applicationServices ?? []).filter((svc) => svc.context === bc.name);
|
|
13197
|
+
if (ctxServices.length === 0) {
|
|
13198
|
+
content += `None captured in exploration yet (run the use-cases pass).
|
|
13199
|
+
|
|
13200
|
+
`;
|
|
13201
|
+
} else {
|
|
13202
|
+
content += `| Service | Use case | Maps to FR |
|
|
13203
|
+
`;
|
|
13204
|
+
content += `|---------|----------|-----------|
|
|
13205
|
+
`;
|
|
13206
|
+
for (const svc of ctxServices) {
|
|
13207
|
+
content += `| \`${svc.name}\` | ${svc.useCase ?? "—"} | ${svc.mapsToFr ?? "—"} |
|
|
13208
|
+
`;
|
|
13209
|
+
}
|
|
13210
|
+
content += `
|
|
13211
|
+
`;
|
|
13212
|
+
}
|
|
13165
13213
|
content += `## Ubiquitous Language
|
|
13166
13214
|
`;
|
|
13167
13215
|
content += `
|
package/package.json
CHANGED
|
@@ -1550,12 +1550,46 @@ export default function (pi: ExtensionAPI) {
|
|
|
1550
1550
|
ctx.ui.notify("Enriching " + moduleFiles.length + " module docs from session " + sessionId, "info");
|
|
1551
1551
|
const lang = readLanguage(ctx.cwd);
|
|
1552
1552
|
|
|
1553
|
+
let servicesCatalog = "(no catalog available)";
|
|
1554
|
+
try {
|
|
1555
|
+
const svcRaw = JSON.parse(fs.readFileSync(sRawPath, "utf-8")) as Record<string, unknown>;
|
|
1556
|
+
const svcAll = Array.isArray(svcRaw.applicationServices) ? (svcRaw.applicationServices as Record<string, unknown>[]) : [];
|
|
1557
|
+
const svcBcs = Array.isArray(svcRaw.boundedContexts) ? (svcRaw.boundedContexts as Record<string, unknown>[]) : [];
|
|
1558
|
+
const ctxFor = (file: string): string => {
|
|
1559
|
+
const wanted = norm(file.replace(/\.md$/, ""));
|
|
1560
|
+
const bc = svcBcs.find((b) => norm(String(b.name ?? "")) === wanted);
|
|
1561
|
+
return bc ? String(bc.name ?? "") : "";
|
|
1562
|
+
};
|
|
1563
|
+
const chunks = moduleFiles.map((f) => {
|
|
1564
|
+
const ctx = ctxFor(f);
|
|
1565
|
+
const svcs = svcAll.filter((sv) => String(sv.context ?? "") === ctx);
|
|
1566
|
+
if (!ctx || svcs.length === 0) return "";
|
|
1567
|
+
const lines = svcs.map((sv) => {
|
|
1568
|
+
const extra = [String(sv.useCase ?? ""), sv.mapsToFr ? "mapsToFr: " + String(sv.mapsToFr) : ""]
|
|
1569
|
+
.filter(Boolean).join(" — ");
|
|
1570
|
+
return `- \u0060${String(sv.name ?? "")}\u0060 : ${extra}`;
|
|
1571
|
+
});
|
|
1572
|
+
return "### " + ctx + " (module doc: " + f + ")\n" + lines.join("\n");
|
|
1573
|
+
}).filter(Boolean);
|
|
1574
|
+
if (chunks.length > 0) servicesCatalog = chunks.join("\n\n");
|
|
1575
|
+
} catch { /* leave fallback text */ }
|
|
1576
|
+
|
|
1553
1577
|
const enrichPrompt = [
|
|
1554
1578
|
"## Task: Complete Architecture Package",
|
|
1555
1579
|
"",
|
|
1556
1580
|
"The scaffold generated basic stubs. Your task is to produce a **complete, interconnected architecture package**",
|
|
1557
1581
|
"that an implementation agent can build from.",
|
|
1558
1582
|
"",
|
|
1583
|
+
"### Application-services catalog (AUTHORITATIVE — from the exploration use-cases pass)",
|
|
1584
|
+
"",
|
|
1585
|
+
"The Application Layer section of EVERY module doc you enrich must list exactly these",
|
|
1586
|
+
"application services for that module's bounded context — EXACT names, use-case, and",
|
|
1587
|
+
"FR mapping. Do NOT rename, drop, or substitute services, and do not invent services",
|
|
1588
|
+
"that replace them. Extra controllers/adapters/query helpers may be added BELOW the",
|
|
1589
|
+
"catalog, but every catalog entry must appear verbatim:",
|
|
1590
|
+
"",
|
|
1591
|
+
servicesCatalog,
|
|
1592
|
+
"",
|
|
1559
1593
|
"**YOU MUST FOLLOW THESE 3 STEPS IN ORDER. Do not skip steps or reorder them.**",
|
|
1560
1594
|
"",
|
|
1561
1595
|
"### Source Data",
|
|
@@ -1711,6 +1745,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
1711
1745
|
|
|
1712
1746
|
const explorationDir = path.join(ctx.cwd, ".pi", "domain", "exploration");
|
|
1713
1747
|
const sessionPath = path.join(explorationDir, sessionId + ".md");
|
|
1748
|
+
const modulesDir = path.join(ctx.cwd, ".pi", "architecture", "modules");
|
|
1749
|
+
const norm = (n: string) => n.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1714
1750
|
const checks: string[] = [];
|
|
1715
1751
|
let allPassed = true;
|
|
1716
1752
|
|
|
@@ -1725,6 +1761,105 @@ export default function (pi: ExtensionAPI) {
|
|
|
1725
1761
|
checks.push(content.includes("## Ubiquitous Language") ? " PASS Ubiquitous language section" : " FAIL Missing ubiquitous language section");
|
|
1726
1762
|
}
|
|
1727
1763
|
|
|
1764
|
+
// Application-services drift gate (root cause: use-cases stopped at the
|
|
1765
|
+
// exploration layer). Every catalog service must be present in its module
|
|
1766
|
+
// doc's Application Layer catalog block; Implemented rows must resolve to a
|
|
1767
|
+
// real seam class in src; Planned/Seam rows must carry a roadmap/phase
|
|
1768
|
+
// pointer. Catches doc gaps (e.g. evidence-export had no catalog block) and
|
|
1769
|
+
// paper claims (doc says Implemented, code has no such seam).
|
|
1770
|
+
const rawVPath = sessionPath.replace(/\.md$/, ".raw.json");
|
|
1771
|
+
if (fs.existsSync(rawVPath)) {
|
|
1772
|
+
try {
|
|
1773
|
+
const rawV = JSON.parse(fs.readFileSync(rawVPath, "utf-8")) as Record<string, unknown>;
|
|
1774
|
+
const svcV = Array.isArray(rawV.applicationServices) ? (rawV.applicationServices as Record<string, unknown>[]) : [];
|
|
1775
|
+
if (svcV.length > 0) {
|
|
1776
|
+
const vModules = fs.readdirSync(modulesDir).filter((f) => f.endsWith(".md") && f !== "module-template.md");
|
|
1777
|
+
const typeExists = (typeName: string): boolean => {
|
|
1778
|
+
const srcBase = path.join(ctx.cwd, "src");
|
|
1779
|
+
if (!fs.existsSync(srcBase)) return false;
|
|
1780
|
+
const target = typeName.replace(/[^A-Za-z0-9_]/g, "");
|
|
1781
|
+
let found = false;
|
|
1782
|
+
const walk = (dir: string, dep: number): void => {
|
|
1783
|
+
if (found || dep > 9) return;
|
|
1784
|
+
let entries;
|
|
1785
|
+
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
|
|
1786
|
+
for (const e of entries) {
|
|
1787
|
+
if (e.name === "node_modules" || e.name === "target" || e.name === ".git" || e.name === "dist") continue;
|
|
1788
|
+
const full = path.join(dir, e.name);
|
|
1789
|
+
if (e.isFile() && (e.name === target + ".java" || e.name === target + ".kt" || e.name === target + ".ts")) { found = true; return; }
|
|
1790
|
+
if (e.isDirectory()) walk(full, dep + 1);
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
walk(srcBase, 0);
|
|
1794
|
+
return found;
|
|
1795
|
+
};
|
|
1796
|
+
const ctxNames = new Map<string, string>(); // norm(ctx) -> ctx
|
|
1797
|
+
const svcByCtx = new Map<string, string[]>();
|
|
1798
|
+
for (const sv of svcV) {
|
|
1799
|
+
const ctx = String(sv.context ?? ""); const nm = String(sv.name ?? "");
|
|
1800
|
+
if (!ctx || !nm) continue;
|
|
1801
|
+
ctxNames.set(norm(ctx), ctx);
|
|
1802
|
+
const arr = svcByCtx.get(ctx) ?? [];
|
|
1803
|
+
arr.push(nm); svcByCtx.set(ctx, arr);
|
|
1804
|
+
}
|
|
1805
|
+
let issues = 0;
|
|
1806
|
+
for (const [normCtx, ctx] of ctxNames) {
|
|
1807
|
+
const docFile = vModules.find((f) => norm(f.replace(/\.md$/, "")) === normCtx) ?? "";
|
|
1808
|
+
if (!docFile) {
|
|
1809
|
+
checks.push(" FAIL Module doc not found for context " + ctx + " (has " + svcByCtx.get(ctx)!.length + " catalog services)");
|
|
1810
|
+
issues++; continue;
|
|
1811
|
+
}
|
|
1812
|
+
const docText = fs.readFileSync(path.join(modulesDir, docFile), "utf-8");
|
|
1813
|
+
const catNames = svcByCtx.get(ctx)!;
|
|
1814
|
+
let miss = 0;
|
|
1815
|
+
for (const nm of catNames) if (!docText.includes(nm)) miss++;
|
|
1816
|
+
if (miss > 0) { checks.push(" FAIL " + docFile + " missing " + miss + " catalog service name(s): " + catNames.filter((n) => !docText.includes(n)).join(", ")); issues += miss; }
|
|
1817
|
+
if (!docText.includes("Service (canonical)")) {
|
|
1818
|
+
checks.push(" FAIL " + docFile + " has no Application Layer catalog block (header 'Service (canonical)') for " + catNames.length + " catalog services");
|
|
1819
|
+
issues++;
|
|
1820
|
+
}
|
|
1821
|
+
// Parse catalog table rows: | `Service` | use case | fr | Status | Delivered by |
|
|
1822
|
+
const block = docText.slice(docText.indexOf("### Application Layer") >= 0 ? docText.indexOf("### Application Layer") : 0);
|
|
1823
|
+
for (const line of block.split("\n")) {
|
|
1824
|
+
if (!line.trim().startsWith("|")) continue;
|
|
1825
|
+
const cells = line.split("|").map((c) => c.trim());
|
|
1826
|
+
if (cells.length < 6) continue;
|
|
1827
|
+
const svcName = cells[1].replace(/^`|`$/g, "");
|
|
1828
|
+
if (!catNames.includes(svcName)) continue; // catalog row only
|
|
1829
|
+
const statusCell = cells[4] + " " + cells[5];
|
|
1830
|
+
const seamCell = cells[5];
|
|
1831
|
+
if (/implemented/i.test(statusCell) && !/planned|seam/i.test(statusCell)) {
|
|
1832
|
+
const seamTokens = Array.from(seamCell.matchAll(/`([A-Za-z0-9_]+)`/g)).map((m) => m[1]);
|
|
1833
|
+
if (seamTokens.length === 0 && !/[A-Z][A-Za-z0-9_]+/.test(seamCell)) {
|
|
1834
|
+
checks.push(" FAIL " + docFile + ": Implemented catalog service " + svcName + " has no seam class named in the doc");
|
|
1835
|
+
issues++;
|
|
1836
|
+
} else {
|
|
1837
|
+
for (const tk of seamTokens.length > 0 ? seamTokens : seamCell.match(/[A-Z][A-Za-z0-9_]+/g) ?? []) {
|
|
1838
|
+
if (!typeExists(tk)) {
|
|
1839
|
+
checks.push(" FAIL " + docFile + ": Implemented service " + svcName + " names seam " + tk + " but no such type exists in src");
|
|
1840
|
+
issues++;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
} else if (/planned|seam/i.test(statusCell)) {
|
|
1845
|
+
if (!/phase|roadmap|later|projection|pending|seam|intake|console|partial|deterministic/i.test(statusCell)) {
|
|
1846
|
+
checks.push(" FAIL " + docFile + ": catalog service " + svcName + " is Planned/Seam without a roadmap/phase pointer");
|
|
1847
|
+
issues++;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
checks.push(issues === 0
|
|
1853
|
+
? " PASS Catalog blocks + seams verified for all " + svcV.length + " application services"
|
|
1854
|
+
: " FAIL " + issues + " catalog/seam issue(s)");
|
|
1855
|
+
if (issues > 0) allPassed = false;
|
|
1856
|
+
} else {
|
|
1857
|
+
checks.push(" PASS No application services in session (use-cases pass not run)");
|
|
1858
|
+
}
|
|
1859
|
+
} catch { /* ignore */ }
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
|
|
1728
1863
|
const header = allPassed ? "Domain Validation - All Checks Passed" : "Domain Validation - Some Checks Failed";
|
|
1729
1864
|
ctx.ui.notify(header, allPassed ? "success" : "error");
|
|
1730
1865
|
|