@aisdlc/core 1.3.0 → 1.3.2

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.cjs CHANGED
@@ -750,6 +750,12 @@ function walkMdFiles(dir, fileList = [], excludeDirs = [
750
750
  "node_modules",
751
751
  ".git",
752
752
  "dist",
753
+ "bin",
754
+ "obj",
755
+ "build",
756
+ "out",
757
+ "target",
758
+ "coverage",
753
759
  ".changeset",
754
760
  "scratch",
755
761
  "test-scaffold",
@@ -761,7 +767,9 @@ function walkMdFiles(dir, fileList = [], excludeDirs = [
761
767
  ".claude",
762
768
  ".cursor",
763
769
  ".github",
764
- ".vscode"
770
+ ".vscode",
771
+ ".vs",
772
+ ".idea"
765
773
  ]) {
766
774
  try {
767
775
  if (!fs6__namespace.existsSync(dir)) return fileList;
@@ -2080,6 +2088,7 @@ var TYPE_TO_SCHEMA_MAP = {
2080
2088
  "security-requirement": "schemas/security/security-req.schema.json",
2081
2089
  "threat-actor": "schemas/security/threat-actor.schema.json",
2082
2090
  // Architecture
2091
+ "architecture-introduction": "schemas/architecture/introduction-and-goals.schema.json",
2083
2092
  "architecture-decision-record": "schemas/architecture/adr.schema.json",
2084
2093
  component: "schemas/architecture/component.schema.json",
2085
2094
  // Safety
@@ -2123,6 +2132,7 @@ var PREFIX_TAXONOMY = [
2123
2132
  ["HAZ-", "hazard"],
2124
2133
  ["SAF-REQ-", "safety-requirement"],
2125
2134
  ["SAF-", "safety-requirement"],
2135
+ ["ARCH-INTRO-", "architecture-introduction"],
2126
2136
  ["ADR-", "architecture-decision-record"],
2127
2137
  ["CMP-", "component"],
2128
2138
  ["MAN-USER-", "user-manual"],
@@ -3312,10 +3322,18 @@ var SKIPPED_DIR_NAMES = /* @__PURE__ */ new Set([
3312
3322
  "node_modules",
3313
3323
  ".git",
3314
3324
  "dist",
3325
+ "bin",
3326
+ "obj",
3327
+ "build",
3328
+ "out",
3329
+ "target",
3330
+ "coverage",
3315
3331
  "scratch",
3316
3332
  "fixtures",
3317
3333
  "templates",
3318
- "examples"
3334
+ "examples",
3335
+ ".vs",
3336
+ ".idea"
3319
3337
  ]);
3320
3338
  function shouldSkipDir(name) {
3321
3339
  return SKIPPED_DIR_NAMES.has(name) || name.startsWith("temp-");
@@ -3417,8 +3435,14 @@ function verifyTraceability(options = {}) {
3417
3435
  });
3418
3436
  }
3419
3437
  }
3420
- if (relFile.includes("architecture/") || relFile.includes("06_runtime_view") || relFile.includes("08_security_concept") || relFile.includes("09_decisions")) {
3421
- architectureViews.push({ file: relFile, content });
3438
+ const isArchIntro = frontmatter.type === "architecture-introduction" || frontmatter.id !== void 0 && String(frontmatter.id).trim().startsWith("ARCH-INTRO-");
3439
+ if (!isArchIntro && (relFile.includes("architecture/") || relFile.includes("06_runtime_view") || relFile.includes("08_security_concept") || relFile.includes("09_decisions"))) {
3440
+ architectureViews.push({
3441
+ file: relFile,
3442
+ id: frontmatter.id ? String(frontmatter.id).trim() : void 0,
3443
+ type: typeof frontmatter.type === "string" ? frontmatter.type.trim() : void 0,
3444
+ content
3445
+ });
3422
3446
  }
3423
3447
  } catch {
3424
3448
  }
@@ -3501,6 +3525,14 @@ function verifyTraceability(options = {}) {
3501
3525
  productTraces.push(...associatedHandoff.subgraph.abuseCases);
3502
3526
  }
3503
3527
  }
3528
+ for (const [artId, artEntry] of artifactMap.entries()) {
3529
+ if (artEntry.type === "architecture-introduction" || artId.startsWith("ARCH-INTRO-")) {
3530
+ const citedGoals = artEntry.frontmatter["cites-quality-goals"];
3531
+ if (Array.isArray(citedGoals) && citedGoals.includes(reqId)) {
3532
+ productTraces.push(artId);
3533
+ }
3534
+ }
3535
+ }
3504
3536
  const validProductTraces = Array.from(
3505
3537
  new Set(productTraces.filter((id) => artifactMap.has(id)))
3506
3538
  );
@@ -3521,8 +3553,9 @@ function verifyTraceability(options = {}) {
3521
3553
  }
3522
3554
  for (const view of architectureViews) {
3523
3555
  if (view.content.includes(reqId)) {
3524
- const viewName = path8__namespace.basename(view.file);
3525
- if (!archTraces.includes(viewName)) archTraces.push(viewName);
3556
+ const isEntityWithId = view.type === "component" || view.type === "adr" || view.type === "architecture-decision-record" || view.type === "security-enclave" || view.id !== void 0 && (view.id.startsWith("CMP-") || view.id.startsWith("ADR-") || view.id.startsWith("SEC-ENC-"));
3557
+ const viewIdentifier = isEntityWithId && view.id ? view.id : path8__namespace.basename(view.file);
3558
+ if (!archTraces.includes(viewIdentifier)) archTraces.push(viewIdentifier);
3526
3559
  }
3527
3560
  }
3528
3561
  const uniqueArchTraces = Array.from(new Set(archTraces));
@@ -3859,7 +3892,7 @@ function scanAllTestArtifacts(rootDir) {
3859
3892
  for (const e of entries) {
3860
3893
  const fullPath = path8__namespace.join(dir, e.name);
3861
3894
  if (e.isDirectory()) {
3862
- if (!["node_modules", ".git", "dist", ".changeset", "scratch", "fixtures", "templates", "examples"].includes(e.name)) {
3895
+ if (!["node_modules", ".git", "dist", "bin", "obj", "build", "out", "target", "coverage", ".changeset", "scratch", "fixtures", "templates", "examples", ".vs", ".idea"].includes(e.name)) {
3863
3896
  walk(fullPath);
3864
3897
  }
3865
3898
  } else {
@@ -7164,7 +7197,31 @@ function buildGraphElements(rootDir = process.cwd()) {
7164
7197
  for (const n of pdac.drifts) {
7165
7198
  driftTargets.add(n.targetId);
7166
7199
  }
7200
+ const NON_GRAPH_TYPES = /* @__PURE__ */ new Set([
7201
+ "term",
7202
+ "handoff",
7203
+ "agent-handoff",
7204
+ "tasks",
7205
+ "task-plan",
7206
+ "spec-change-proposal",
7207
+ "proposal",
7208
+ "spec-design",
7209
+ "spec-change-design",
7210
+ "design",
7211
+ "delivery-spec",
7212
+ "spec",
7213
+ "pre-merge-audit-report",
7214
+ "user-design-feedback",
7215
+ "release-kpis",
7216
+ "session-telemetry",
7217
+ "license-manifest",
7218
+ "mcp-config",
7219
+ "user-manual",
7220
+ "production-manual",
7221
+ "architecture-glossary"
7222
+ ]);
7167
7223
  const scannedArtifactsMap = /* @__PURE__ */ new Map();
7224
+ const archViewByBasename = /* @__PURE__ */ new Map();
7168
7225
  const artifactDirs = ["product", "architecture", "specs", "security"];
7169
7226
  for (const dirName of artifactDirs) {
7170
7227
  const fullDirPath = path8__namespace.join(rootDir, dirName);
@@ -7174,6 +7231,7 @@ function buildGraphElements(rootDir = process.cwd()) {
7174
7231
  try {
7175
7232
  const fileContent = fs6__namespace.readFileSync(f, "utf-8");
7176
7233
  const relPath = path8__namespace.relative(rootDir, f).replace(/\\/g, "/");
7234
+ if (relPath.includes("/changes/") || relPath.startsWith("changes/")) continue;
7177
7235
  const match = fileContent.match(/^---\r?\n([\s\S]*?)\r?\n---/);
7178
7236
  if (!match) continue;
7179
7237
  let fm = {};
@@ -7185,8 +7243,14 @@ function buildGraphElements(rootDir = process.cwd()) {
7185
7243
  const id = typeof fm.id === "string" ? fm.id.trim() : void 0;
7186
7244
  if (!id) continue;
7187
7245
  let type = typeof fm.type === "string" ? fm.type.trim() : "";
7246
+ if (NON_GRAPH_TYPES.has(type) || id.startsWith("TERM-") || id.startsWith("HOF-") || id.startsWith("AHOF-") || id.startsWith("CHG-") || id.startsWith("DSG-") || id.startsWith("SPEC-") || id.startsWith("TSK-") || id.startsWith("UDF-") || id.startsWith("AUDIT-")) {
7247
+ continue;
7248
+ }
7188
7249
  let layer = "product";
7189
- if (id.startsWith("JRN-") || type === "journey") {
7250
+ if (id.startsWith("ARCH-INTRO-") || type === "architecture-introduction") {
7251
+ type = "architecture-introduction";
7252
+ layer = "product";
7253
+ } else if (id.startsWith("JRN-") || type === "journey") {
7190
7254
  type = "journey";
7191
7255
  layer = "product";
7192
7256
  } else if (id.startsWith("ACT-THREAT-") || type === "threat-actor") {
@@ -7219,16 +7283,19 @@ function buildGraphElements(rootDir = process.cwd()) {
7219
7283
  } else if (id.startsWith("SEC-REQ-") || type === "security-requirement") {
7220
7284
  type = "security-requirement";
7221
7285
  layer = "requirement";
7222
- } else if (id.startsWith("FR-") || id.startsWith("QR-") || id.startsWith("CON-") || type === "requirement") {
7286
+ } else if (id.startsWith("FR-") || id.startsWith("QR-") || id.startsWith("CON-") || type === "requirement" || type === "functional-requirement" || type === "quality-requirement") {
7223
7287
  type = "requirement";
7224
7288
  layer = "requirement";
7289
+ } else if (id.startsWith("ARCH-") || relPath.includes("architecture/")) {
7290
+ type = "architecture";
7291
+ layer = "architecture";
7225
7292
  } else {
7226
7293
  type = type || "product";
7227
7294
  layer = "product";
7228
7295
  }
7229
7296
  const title = typeof fm.title === "string" ? fm.title.trim() : id;
7230
7297
  const content = fileContent.replace(/^---\r?\n[\s\S]*?\r?\n---/, "").trim();
7231
- scannedArtifactsMap.set(id, {
7298
+ const scannedArt = {
7232
7299
  id,
7233
7300
  type,
7234
7301
  title,
@@ -7236,7 +7303,12 @@ function buildGraphElements(rootDir = process.cwd()) {
7236
7303
  filePath: relPath,
7237
7304
  content,
7238
7305
  frontmatter: fm
7239
- });
7306
+ };
7307
+ if (layer === "architecture" && type === "architecture") {
7308
+ archViewByBasename.set(path8__namespace.basename(relPath), scannedArt);
7309
+ } else {
7310
+ scannedArtifactsMap.set(id, scannedArt);
7311
+ }
7240
7312
  } catch {
7241
7313
  }
7242
7314
  }
@@ -7245,7 +7317,7 @@ function buildGraphElements(rootDir = process.cwd()) {
7245
7317
  for (const r of trace.rows) {
7246
7318
  const isOk = (r.productStatus === "COMPLIANT" || r.productStatus === "CONFORME") && (r.archStatus === "COMPLIANT" || r.archStatus === "CONFORME") && (r.testStatus === "COMPLIANT" || r.testStatus === "CONFORME");
7247
7319
  const status = isOk ? "COMPLIANT" : "ORPHAN";
7248
- const reqType = r.id.startsWith("SEC-REQ-") ? "security-requirement" : r.type || "requirement";
7320
+ const reqType = r.id.startsWith("SEC-REQ-") ? "security-requirement" : "requirement";
7249
7321
  nodeMap.set(r.id, {
7250
7322
  id: r.id,
7251
7323
  label: r.id,
@@ -7271,16 +7343,18 @@ function buildGraphElements(rootDir = process.cwd()) {
7271
7343
  const u = up.trim();
7272
7344
  if (u && u !== "NINGUNO" && u !== "NONE") {
7273
7345
  const isAbuse = u.startsWith("ABUSE-");
7346
+ const isArchIntro = u.startsWith("ARCH-INTRO-");
7347
+ const rel = isAbuse ? "mitigated-by" : isArchIntro ? "defines-goal" : "derives-from";
7274
7348
  addEdge({
7275
7349
  id: `edge-${u}-${r.id}`,
7276
7350
  source: u,
7277
7351
  target: r.id,
7278
- label: isAbuse ? "mitigated-by" : "derives-from",
7279
- relation: isAbuse ? "mitigated-by" : "derives-from",
7352
+ label: rel,
7353
+ relation: rel,
7280
7354
  status
7281
7355
  });
7282
7356
  if (!nodeMap.has(u)) {
7283
- const upType = u.startsWith("ACT-") ? "actor" : u.startsWith("UC-") ? "use-case" : u.startsWith("BR-") ? "business-rule" : u.startsWith("ABUSE-") ? "abuse-case" : "product";
7357
+ const upType = u.startsWith("ARCH-INTRO-") ? "architecture-introduction" : u.startsWith("ACT-") ? "actor" : u.startsWith("UC-") ? "use-case" : u.startsWith("BR-") ? "business-rule" : u.startsWith("ABUSE-") ? "abuse-case" : "product";
7284
7358
  nodeMap.set(u, {
7285
7359
  id: u,
7286
7360
  label: u,
@@ -7305,13 +7379,16 @@ function buildGraphElements(rootDir = process.cwd()) {
7305
7379
  });
7306
7380
  if (!nodeMap.has(a)) {
7307
7381
  const aType = a.startsWith("CMP-") ? "component" : a.startsWith("ADR-") ? "adr" : a.startsWith("SEC-ENC-") ? "security-enclave" : "architecture";
7382
+ const viewArt = archViewByBasename.get(a);
7308
7383
  nodeMap.set(a, {
7309
7384
  id: a,
7310
7385
  label: a,
7311
- title: a,
7386
+ title: viewArt?.title || a,
7312
7387
  type: aType,
7313
7388
  layer: "architecture",
7314
- status: "COMPLIANT"
7389
+ status: "COMPLIANT",
7390
+ filePath: viewArt?.filePath,
7391
+ content: viewArt?.content
7315
7392
  });
7316
7393
  }
7317
7394
  }
@@ -7375,7 +7452,80 @@ function buildGraphElements(rootDir = process.cwd()) {
7375
7452
  }
7376
7453
  for (const art of scannedArtifactsMap.values()) {
7377
7454
  const fm = art.frontmatter;
7378
- if (art.type === "journey") {
7455
+ if (art.type === "architecture-introduction") {
7456
+ const citedActors = Array.isArray(fm["cites-product-actors"]) ? fm["cites-product-actors"] : [];
7457
+ for (const actId of citedActors) {
7458
+ if (typeof actId === "string" && actId.trim()) {
7459
+ const a = actId.trim();
7460
+ if (!nodeMap.has(a)) {
7461
+ nodeMap.set(a, {
7462
+ id: a,
7463
+ label: a,
7464
+ title: a,
7465
+ type: "actor",
7466
+ layer: "product",
7467
+ status: "COMPLIANT"
7468
+ });
7469
+ }
7470
+ addEdge({
7471
+ id: `edge-${art.id}-${a}`,
7472
+ source: art.id,
7473
+ target: a,
7474
+ label: "identifies",
7475
+ relation: "identifies",
7476
+ status: "COMPLIANT"
7477
+ });
7478
+ }
7479
+ }
7480
+ const citedUcs = Array.isArray(fm["cites-use-cases"]) ? fm["cites-use-cases"] : [];
7481
+ for (const ucId of citedUcs) {
7482
+ if (typeof ucId === "string" && ucId.trim()) {
7483
+ const u = ucId.trim();
7484
+ if (!nodeMap.has(u)) {
7485
+ nodeMap.set(u, {
7486
+ id: u,
7487
+ label: u,
7488
+ title: u,
7489
+ type: "use-case",
7490
+ layer: "product",
7491
+ status: "COMPLIANT"
7492
+ });
7493
+ }
7494
+ addEdge({
7495
+ id: `edge-${art.id}-${u}`,
7496
+ source: art.id,
7497
+ target: u,
7498
+ label: "envisions",
7499
+ relation: "envisions",
7500
+ status: "COMPLIANT"
7501
+ });
7502
+ }
7503
+ }
7504
+ const citedGoals = Array.isArray(fm["cites-quality-goals"]) ? fm["cites-quality-goals"] : [];
7505
+ for (const qrId of citedGoals) {
7506
+ if (typeof qrId === "string" && qrId.trim()) {
7507
+ const q = qrId.trim();
7508
+ if (!nodeMap.has(q)) {
7509
+ nodeMap.set(q, {
7510
+ id: q,
7511
+ label: q,
7512
+ title: q,
7513
+ type: q.startsWith("SEC-REQ-") ? "security-requirement" : "requirement",
7514
+ layer: "requirement",
7515
+ status: "COMPLIANT"
7516
+ });
7517
+ }
7518
+ addEdge({
7519
+ id: `edge-${art.id}-${q}`,
7520
+ source: art.id,
7521
+ target: q,
7522
+ label: "defines-goal",
7523
+ relation: "defines-goal",
7524
+ status: "COMPLIANT"
7525
+ });
7526
+ }
7527
+ }
7528
+ } else if (art.type === "journey") {
7379
7529
  const persona = typeof fm.persona === "string" ? fm.persona : typeof fm.actor === "string" ? fm.actor : void 0;
7380
7530
  if (persona) {
7381
7531
  if (!nodeMap.has(persona)) {
@@ -7443,7 +7593,31 @@ function buildGraphElements(rootDir = process.cwd()) {
7443
7593
  status: "COMPLIANT"
7444
7594
  });
7445
7595
  }
7446
- const governedBy = Array.isArray(fm["governed-by"]) ? fm["governed-by"] : [];
7596
+ const supportingActors = Array.isArray(fm["supporting-actors"]) ? fm["supporting-actors"] : Array.isArray(fm["secondary-actors"]) ? fm["secondary-actors"] : [];
7597
+ for (const actorId of supportingActors) {
7598
+ if (typeof actorId === "string" && actorId.trim()) {
7599
+ const a = actorId.trim();
7600
+ if (!nodeMap.has(a)) {
7601
+ nodeMap.set(a, {
7602
+ id: a,
7603
+ label: a,
7604
+ title: a,
7605
+ type: "actor",
7606
+ layer: "product",
7607
+ status: "COMPLIANT"
7608
+ });
7609
+ }
7610
+ addEdge({
7611
+ id: `edge-${a}-${art.id}`,
7612
+ source: a,
7613
+ target: art.id,
7614
+ label: "initiates",
7615
+ relation: "initiates",
7616
+ status: "COMPLIANT"
7617
+ });
7618
+ }
7619
+ }
7620
+ const governedBy = Array.isArray(fm["governed-by"]) ? fm["governed-by"] : Array.isArray(fm["business-rules"]) ? fm["business-rules"] : [];
7447
7621
  for (const ruleId of governedBy) {
7448
7622
  if (typeof ruleId === "string" && ruleId.trim()) {
7449
7623
  const r = ruleId.trim();
@@ -7504,7 +7678,31 @@ function buildGraphElements(rootDir = process.cwd()) {
7504
7678
  status: "COMPLIANT"
7505
7679
  });
7506
7680
  }
7507
- const rawTargets = fm["targets-use-case"] ? [fm["targets-use-case"]] : Array.isArray(fm["targets-use-cases"]) ? fm["targets-use-cases"] : Array.isArray(fm["targets"]) ? fm["targets"] : [];
7681
+ const secondaryThreatActors = Array.isArray(fm["secondary-actors"]) ? fm["secondary-actors"] : Array.isArray(fm["supporting-actors"]) ? fm["supporting-actors"] : [];
7682
+ for (const secActor of secondaryThreatActors) {
7683
+ if (typeof secActor === "string" && secActor.trim()) {
7684
+ const sa = secActor.trim();
7685
+ if (!nodeMap.has(sa)) {
7686
+ nodeMap.set(sa, {
7687
+ id: sa,
7688
+ label: sa,
7689
+ title: sa,
7690
+ type: sa.startsWith("ACT-THREAT-") ? "threat-actor" : "actor",
7691
+ layer: "product",
7692
+ status: "COMPLIANT"
7693
+ });
7694
+ }
7695
+ addEdge({
7696
+ id: `edge-${sa}-${art.id}`,
7697
+ source: sa,
7698
+ target: art.id,
7699
+ label: "threatens",
7700
+ relation: "threatens",
7701
+ status: "COMPLIANT"
7702
+ });
7703
+ }
7704
+ }
7705
+ const rawTargets = Array.isArray(fm["targets-use-case"]) ? fm["targets-use-case"] : typeof fm["targets-use-case"] === "string" ? [fm["targets-use-case"]] : Array.isArray(fm["targets-use-cases"]) ? fm["targets-use-cases"] : Array.isArray(fm["targets"]) ? fm["targets"] : [];
7508
7706
  for (const tgt of rawTargets) {
7509
7707
  if (typeof tgt === "string" && tgt.trim()) {
7510
7708
  const t = tgt.trim();
@@ -7569,6 +7767,40 @@ function buildGraphElements(rootDir = process.cwd()) {
7569
7767
  });
7570
7768
  }
7571
7769
  }
7770
+ } else if (art.type === "adr") {
7771
+ const affectedComponents = Array.isArray(fm["affects-components"]) ? fm["affects-components"] : typeof fm["affects-components"] === "string" ? [fm["affects-components"]] : [];
7772
+ for (const cmpId of affectedComponents) {
7773
+ if (typeof cmpId === "string" && cmpId.trim()) {
7774
+ const c = cmpId.trim();
7775
+ if (nodeMap.has(c)) {
7776
+ addEdge({
7777
+ id: `edge-${art.id}-${c}`,
7778
+ source: art.id,
7779
+ target: c,
7780
+ label: "governs",
7781
+ relation: "governs",
7782
+ status: "COMPLIANT"
7783
+ });
7784
+ }
7785
+ }
7786
+ }
7787
+ } else if (art.type === "security-enclave") {
7788
+ const enforcedBy = Array.isArray(fm["enforced-by"]) ? fm["enforced-by"] : typeof fm["enforced-by"] === "string" ? [fm["enforced-by"]] : [];
7789
+ for (const secReq of enforcedBy) {
7790
+ if (typeof secReq === "string" && secReq.trim()) {
7791
+ const s = secReq.trim();
7792
+ if (nodeMap.has(s)) {
7793
+ addEdge({
7794
+ id: `edge-${s}-${art.id}`,
7795
+ source: s,
7796
+ target: art.id,
7797
+ label: "satisfies",
7798
+ relation: "satisfies",
7799
+ status: "COMPLIANT"
7800
+ });
7801
+ }
7802
+ }
7803
+ }
7572
7804
  }
7573
7805
  }
7574
7806
  for (const [id, node] of nodeMap.entries()) {
@@ -7718,6 +7950,9 @@ function collectDashboardMetrics(rootDir) {
7718
7950
  function escapeHtml(str) {
7719
7951
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
7720
7952
  }
7953
+ function safeJsonForScript(data) {
7954
+ return JSON.stringify(data).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
7955
+ }
7721
7956
  function renderAutonomyModeSection(mode, statusIcon, count, roleDescription, allTasks = []) {
7722
7957
  const modeTasks = (allTasks || []).filter(
7723
7958
  (t) => (t.task?.autonomyMode || "").toUpperCase() === mode
@@ -7829,14 +8064,14 @@ function renderAutonomyModeSection(mode, statusIcon, count, roleDescription, all
7829
8064
  }
7830
8065
  function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard Interactivo de Trazabilidad y Calidad") {
7831
8066
  const cytoscapeScript = getCytoscapeScript();
7832
- const elementsJson = JSON.stringify(graphData.elements);
8067
+ const elementsJson = safeJsonForScript(graphData.elements);
7833
8068
  const now = (/* @__PURE__ */ new Date()).toISOString();
7834
8069
  return `<!DOCTYPE html>
7835
8070
  <html lang="es">
7836
8071
  <head>
7837
8072
  <meta charset="UTF-8">
7838
8073
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7839
- <title>${title}</title>
8074
+ <title>${escapeHtml(title)}</title>
7840
8075
  <style>
7841
8076
  :root {
7842
8077
  --bg-dark: #0f172a;
@@ -8139,6 +8374,7 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8139
8374
  <div class="tool-row">
8140
8375
  <select id="type-filter" class="tool-select" onchange="filterType(this.value)">
8141
8376
  <option value="all">All Typologies</option>
8377
+ <option value="architecture-introduction">Vision &amp; Goals (ARCH-INTRO)</option>
8142
8378
  <option value="journey">Journeys (JRN)</option>
8143
8379
  <option value="actor">Actors (ACT)</option>
8144
8380
  <option value="use-case">Use Cases (UC)</option>
@@ -8173,6 +8409,7 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8173
8409
  <div class="graph-legend">
8174
8410
  <div class="legend-header">Node Typologies</div>
8175
8411
  <div class="legend-items">
8412
+ <div class="legend-item"><span class="legend-dot" style="background:#0f766e; border:2px solid #2dd4bf;"></span><strong>Vision / Goals</strong> (ARCH-INTRO)</div>
8176
8413
  <div class="legend-item"><span class="legend-dot" style="background:#581c87; border:2px solid #c084fc;"></span><strong>Journey</strong> (JRN)</div>
8177
8414
  <div class="legend-item"><span class="legend-dot" style="background:#065f46; border:2px solid #34d399; border-radius:50%;"></span><strong>Actor</strong> (ACT)</div>
8178
8415
  <div class="legend-item"><span class="legend-dot" style="background:#0369a1; border:2px solid #38bdf8;"></span><strong>Use Case</strong> (UC)</div>
@@ -8211,12 +8448,12 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8211
8448
  ${metricsData.trace.rows.map((r) => {
8212
8449
  const isRowOk = (r.productStatus === "COMPLIANT" || r.productStatus === "CONFORME") && (r.archStatus === "COMPLIANT" || r.archStatus === "CONFORME") && (r.testStatus === "COMPLIANT" || r.testStatus === "CONFORME");
8213
8450
  return `
8214
- <tr onclick="focusNode('${r.id}')" onmouseenter="startRowTooltip(event, '${r.id}')" onmouseleave="cancelRowTooltip()" onmousemove="updateRowTooltipPos(event)" style="cursor: pointer;">
8215
- <td><strong><code>${r.id}</code></strong></td>
8216
- <td>${r.title}</td>
8217
- <td><code>${r.productTraces}</code></td>
8218
- <td><code>${r.archTraces}</code></td>
8219
- <td><code>${r.testTraces}</code></td>
8451
+ <tr onclick="focusNode('${escapeHtml(String(r.id || ""))}')" onmouseenter="startRowTooltip(event, '${escapeHtml(String(r.id || ""))}')" onmouseleave="cancelRowTooltip()" onmousemove="updateRowTooltipPos(event)" style="cursor: pointer;">
8452
+ <td><strong><code>${escapeHtml(String(r.id || ""))}</code></strong></td>
8453
+ <td>${escapeHtml(String(r.title || ""))}</td>
8454
+ <td><code>${escapeHtml(String(r.productTraces || ""))}</code></td>
8455
+ <td><code>${escapeHtml(String(r.archTraces || ""))}</code></td>
8456
+ <td><code>${escapeHtml(String(r.testTraces || ""))}</code></td>
8220
8457
  <td><span class="badge ${isRowOk ? "badge-green" : "badge-amber"}">${isRowOk ? "COMPLIANT" : "ORPHAN"}</span></td>
8221
8458
  </tr>
8222
8459
  `;
@@ -8429,7 +8666,7 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8429
8666
  </script>
8430
8667
  <script>
8431
8668
  var elements = ${elementsJson};
8432
- var govTasks = ${JSON.stringify(metricsData.gov.tasks || [])};
8669
+ var govTasks = ${safeJsonForScript(metricsData.gov.tasks || [])};
8433
8670
  var cy = null;
8434
8671
 
8435
8672
  var reqHoverTimer = null;
@@ -8592,6 +8829,19 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8592
8829
  }
8593
8830
  },
8594
8831
  // Typology Styles
8832
+ {
8833
+ selector: 'node.type-architecture-introduction',
8834
+ style: {
8835
+ 'shape': 'round-rectangle',
8836
+ 'background-color': '#0f766e',
8837
+ 'border-color': '#2dd4bf',
8838
+ 'border-width': 3,
8839
+ 'width': 92,
8840
+ 'height': 44,
8841
+ 'font-weight': 'bold',
8842
+ 'text-max-width': '86px'
8843
+ }
8844
+ },
8595
8845
  {
8596
8846
  selector: 'node.type-journey',
8597
8847
  style: {
@@ -8708,7 +8958,7 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8708
8958
  },
8709
8959
  // Fallback Layer styles if type is missing
8710
8960
  {
8711
- selector: 'node.layer-product:not(.type-journey):not(.type-actor):not(.type-use-case):not(.type-usecase):not(.type-business-rule):not(.type-rule):not(.type-abuse-case):not(.type-threat-actor)',
8961
+ selector: 'node.layer-product:not(.type-architecture-introduction):not(.type-journey):not(.type-actor):not(.type-use-case):not(.type-usecase):not(.type-business-rule):not(.type-rule):not(.type-abuse-case):not(.type-threat-actor)',
8712
8962
  style: { 'shape': 'diamond', 'background-color': '#0e7490', 'border-color': '#38bdf8', 'width': 50, 'height': 50 }
8713
8963
  },
8714
8964
  {
@@ -8737,6 +8987,10 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8737
8987
  }
8738
8988
  },
8739
8989
  // Semantic Edge Relations
8990
+ {
8991
+ selector: 'edge.relation-identifies, edge.relation-envisions, edge.relation-defines-goal',
8992
+ style: { 'line-color': '#2dd4bf', 'target-arrow-color': '#2dd4bf', 'width': 2 }
8993
+ },
8740
8994
  {
8741
8995
  selector: 'edge.relation-pursues',
8742
8996
  style: { 'line-color': '#c084fc', 'target-arrow-color': '#c084fc', 'width': 2 }
@@ -8877,7 +9131,10 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8877
9131
  var typeName = (data.type || data.layer || 'node').toLowerCase();
8878
9132
  var typeBadgeColor = '#334155';
8879
9133
  var typeTitle = (data.type || data.layer || 'NODE').toUpperCase();
8880
- if (typeName === 'journey') {
9134
+ if (typeName === 'architecture-introduction') {
9135
+ typeBadgeColor = '#0f766e';
9136
+ typeTitle = 'VISION & GOALS (ARCH-INTRO)';
9137
+ } else if (typeName === 'journey') {
8881
9138
  typeBadgeColor = '#581c87';
8882
9139
  typeTitle = 'JOURNEY (JRN)';
8883
9140
  } else if (typeName === 'actor') {
@@ -8943,6 +9200,11 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
8943
9200
  if (!cy) return;
8944
9201
  if (type === 'all') {
8945
9202
  cy.elements().show();
9203
+ } else if (type === 'architecture-introduction') {
9204
+ cy.elements().hide();
9205
+ var nodes = cy.nodes('.type-architecture-introduction');
9206
+ nodes.show();
9207
+ nodes.connectedEdges().show();
8946
9208
  } else if (type === 'journey') {
8947
9209
  cy.elements().hide();
8948
9210
  var nodes = cy.nodes('.type-journey');
@@ -9062,9 +9324,10 @@ function renderDashboardHtml(graphData, metricsData, title = "AI-SDLC: Dashboard
9062
9324
 
9063
9325
  function switchTab(name) {
9064
9326
  hideTooltip();
9065
- document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('active'); });
9327
+ document.querySelectorAll('.tab-btn').forEach(function(b) {
9328
+ b.classList.toggle('active', b.getAttribute('onclick') === "switchTab('" + name + "')");
9329
+ });
9066
9330
  document.querySelectorAll('.tab-panel').forEach(function(p) { p.classList.remove('active'); });
9067
- event.target?.classList?.add('active');
9068
9331
  var p = document.getElementById('tab-' + name);
9069
9332
  if (p) p.classList.add('active');
9070
9333
  if (name === 'graph' && cy) {
@@ -9278,14 +9541,20 @@ var SPECIALIZED_AGENT_TEMPLATES = [
9278
9541
  {
9279
9542
  id: "agent-product-analyst",
9280
9543
  title: "Product Analyst / Scribe",
9281
- description: "Assist the human Product Owner in exploring, modeling, and refining product definition using ProductShape (ACT-*, UC-*, FR-*, QR-*, BR-*).",
9282
- globs: "product/**, specs/product/**, templates/product/**",
9544
+ description: "Assist the human Product Owner in exploring, modeling, and refining product definition using NAF v4 Enterprise & Capability Vision (ARCH-INTRO-*) and ProductShape (ACT-*, UC-*, FR-*, QR-*, BR-*).",
9545
+ globs: "product/**, specs/product/**, templates/product/**, templates/architecture/introduction-and-goals.template.md",
9283
9546
  body: `## Role & Mission
9284
9547
  - **Role**: Product Analyst Agent (\`agent-product-analyst\`) and Technical Scribe (AI as Scribe) of the AI-SDLC framework.
9285
- - **Mission**: Transform natural language business intent into canonical ProductShape artifacts (\`ACT-*\`, \`JRN-*\`, \`UC-*\`, \`BR-*\`, \`TERM-*\`, \`FR-*\`, \`QR-*\`) 100% compliant with JSON schemas.
9548
+ - **Mission**: Capture new product intent via NAF v4 Enterprise & Capability Vision (\`ARCH-INTRO-*\`) and transform natural language business intent into canonical ProductShape artifacts (\`ACT-*\`, \`JRN-*\`, \`UC-*\`, \`BR-*\`, \`TERM-*\`, \`FR-*\`, \`QR-*\`) 100% compliant with JSON schemas.
9549
+
9550
+ ## Phase 0: Greenfield Product Inception (New Product Intent)
9551
+ - **Trigger**: When the user expresses intent to create a new product from scratch with the framework (or when \`specs/product/\` has no baseline product model yet), initiate **Phase 0** before any SDD change (\`change:new\`) or implementation:
9552
+ 1. **Structured Discovery Interview (3\u20135 Questions)**: Ask a concise 3\u20135 question interview to clarify: (a) core problem and mission statement, (b) primary actors/stakeholders (\`ACT-*\`), (c) essential MVP capabilities/use cases (\`UC-*\`), and (d) top 3\u20135 priority quality goals and constraints (\`QR-*\`, \`CON-*\`).
9553
+ 2. **Enterprise & Capability Vision (\`ARCH-INTRO-001\`)**: Draft the root vision artifact (\`type: architecture-introduction\`, \`naf-perspective: "Enterprise & Capability"\`, \`status: draft\`) using \`templates/architecture/introduction-and-goals.template.md\` (\`schemas/architecture/introduction-and-goals.schema.json\`).
9554
+ 3. **ProductShape Derivation**: Derive the initial draft artifacts (\`ACT-*\`, \`UC-*\`, \`BR-*\`, \`FR-*\`, \`QR-*\` with \`status: draft\`) in \`specs/product/\` linked to \`ARCH-INTRO-001\` for human Product Owner review.
9286
9555
 
9287
9556
  ## Operational Directives & Guardrails
9288
- - Every generated artifact must strictly adhere to the canonical Markdown and YAML frontmatter format in \`schemas/product/\`.
9557
+ - Every generated artifact must strictly adhere to the canonical Markdown and YAML frontmatter format in \`schemas/product/\` and \`schemas/architecture/introduction-and-goals.schema.json\`.
9289
9558
  - \`status\` ALWAYS starts as \`draft\`. Creating artifacts directly as \`active\` or \`approved\` is forbidden.
9290
9559
  - Always write relationships in their single canonical direction (\`derives-from: [UC-*]\`, \`primary-actor: ACT-*\`).
9291
9560
  - In \`UC-*\`, format section \`1. Intent and Outcome\` under the standard English structure: \`As a <ACT-ID>... I want <action>... To <outcome>...\`.
@@ -9533,9 +9802,10 @@ This file defines the operational rules and specialized role mappings for Google
9533
9802
  ## 2. Specialized Roles Mapping
9534
9803
 
9535
9804
  ### 1. \`agent-product-analyst\` (Product Analyst / Scribe)
9536
- - **Mission**: Assist in defining and refining the product model using ProductShape.
9805
+ - **Mission**: Capture new product intent via NAF v4 Enterprise & Capability Vision (\`ARCH-INTRO-*\`) and define/refine the product model using ProductShape.
9806
+ - **Phase 0 (Greenfield Product Inception)**: When creating a new product from scratch (or when \`specs/product/\` has no baseline), run a concise 3\u20135 question discovery interview (mission/problem, actors \`ACT-*\`, MVP capabilities \`UC-*\`, priority quality goals \`QR-*\`), draft \`ARCH-INTRO-001\` (\`templates/architecture/introduction-and-goals.template.md\`), and derive initial \`ACT-*\`, \`UC-*\`, \`BR-*\`, \`FR-*\`, and \`QR-*\` drafts.
9537
9807
  - **Input**: Business intent or natural language specification.
9538
- - **Output**: Markdown artifacts with YAML frontmatter compliant with \`schemas/product/\` (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`).
9808
+ - **Output**: Markdown artifacts with YAML frontmatter compliant with \`schemas/architecture/introduction-and-goals.schema.json\` (\`ARCH-INTRO-*\`) and \`schemas/product/\` (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`).
9539
9809
  - **Guardrails**:
9540
9810
  - \`status\` always starts in \`draft\`.
9541
9811
  - In \`UC-*\`, format section \`1. Intent and Outcome\` under the standard English structure: \`As a <ACT-ID>... I want <action>... To <outcome>...\`.
@@ -9666,7 +9936,7 @@ Before finalizing changes or proposing commits:
9666
9936
  ## 4. Specialized Roles Mapping
9667
9937
  | Role | Mission (summary) |
9668
9938
  | :--- | :--- |
9669
- | \`agent-product-analyst\` | ProductShape artifacts (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`); status starts \`draft\`. |
9939
+ | \`agent-product-analyst\` | Phase 0 NAF v4 Enterprise & Capability Vision (\`ARCH-INTRO-*\`, 3\u20135 question interview) + ProductShape artifacts (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`); status starts \`draft\`. |
9670
9940
  | \`agent-threat-modeler\` | STRIDE/OWASP threat triad (\`ACT-THREAT-*\`, \`ABUSE-*\`, \`SEC-REQ-*\`). |
9671
9941
  | \`agent-system-architect\` | Modular arc42 + NAF v4 architecture (\`CMP-*\`, Mermaid diagrams, \`ADR-*\`). |
9672
9942
  | \`agent-qa-engineer\` | FAILING BDD/Gherkin suites before \`agent-developer\` writes code. |
@@ -9701,6 +9971,7 @@ Canonical Reference: [\`process/09_agent_protocols.md\`](process/09_agent_protoc
9701
9971
 
9702
9972
  ## 1. Identifier Taxonomy and JSON Schemas
9703
9973
  Every generated or modified artifact must follow canonical naming and satisfy its schema in \`schemas/\`:
9974
+ - Enterprise & Capability Vision (Phase 0): \`ARCH-INTRO-[NUM3]\` (\`schemas/architecture/introduction-and-goals.schema.json\`)
9704
9975
  - Product Actors: \`ACT-[SUFFIX]\` (\`schemas/product/actor.schema.json\`)
9705
9976
  - Use Cases: \`UC-[SUFFIX]\` (\`schemas/product/use-case.schema.json\`)
9706
9977
  - Functional Requirements: \`FR-[SUFFIX]-[NUM3]\` (\`schemas/product/requirement.schema.json\`)
@@ -9711,6 +9982,7 @@ Every generated or modified artifact must follow canonical naming and satisfy it
9711
9982
  - Security Requirements: \`SEC-REQ-[SUFFIX]\` (\`schemas/security/security-req.schema.json\`)
9712
9983
 
9713
9984
  ## 2. "AI as Scribe" Protocol Rules
9985
+ - **Phase 0 (New Product Inception)**: When starting a new product, conduct a 3\u20135 question discovery interview, instantiate \`ARCH-INTRO-001\` (\`naf-perspective: "Enterprise & Capability"\`) in \`draft\`, and derive \`ACT-*\`, \`UC-*\`, \`BR-*\`, \`FR-*\`, and \`QR-*\`.
9714
9986
  - **Initial Status**: Every new artifact strictly starts with \`status: draft\`. Creating artifacts directly as \`active\` or \`approved\` is forbidden.
9715
9987
  - **Gherkin Acceptance Criteria**: In every \`FR-*\` requirement, include a \`\`\`gherkin block with tags \`@<ID> @automated @regression\` and at least one \`Scenario Outline\` with an \`Examples\` data table.
9716
9988
  - **Security Mitigations**: Every \`SEC-REQ-*\` must include negative Gherkin tests (\`@security @mitigation\`).
@@ -9792,9 +10064,10 @@ npx tsx packages/cli/src/index.ts sdd integrate --change <chg-id>
9792
10064
  ## 3. Specialized Roles Mapping
9793
10065
 
9794
10066
  ### 1. \`agent-product-analyst\` (Product Analyst / Scribe)
9795
- - **Mission**: Assist in defining and refining the product model using ProductShape.
10067
+ - **Mission**: Capture new product intent via NAF v4 Enterprise & Capability Vision (\`ARCH-INTRO-*\`) and define/refine the product model using ProductShape.
10068
+ - **Phase 0 (Greenfield Product Inception)**: When creating a new product from scratch (or when \`specs/product/\` has no baseline), run a concise 3\u20135 question discovery interview (mission/problem, actors \`ACT-*\`, MVP capabilities \`UC-*\`, priority quality goals \`QR-*\`), draft \`ARCH-INTRO-001\` (\`templates/architecture/introduction-and-goals.template.md\`), and derive initial \`ACT-*\`, \`UC-*\`, \`BR-*\`, \`FR-*\`, and \`QR-*\` drafts.
9796
10069
  - **Input**: Business intent or natural language specification.
9797
- - **Output**: Markdown artifacts with YAML frontmatter compliant with \`schemas/product/\` (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`).
10070
+ - **Output**: Markdown artifacts with YAML frontmatter compliant with \`schemas/architecture/introduction-and-goals.schema.json\` (\`ARCH-INTRO-*\`) and \`schemas/product/\` (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`).
9798
10071
  - **Guardrails**: \`status\` always starts in \`draft\`. Mandatory Gherkin criteria with \`@<ID> @automated @regression\`.
9799
10072
 
9800
10073
  ### 2. \`agent-threat-modeler\` (Threat Modeler and Security Specialist)
@@ -9953,7 +10226,7 @@ Non-Negotiable Quality Thresholds (\`quality-policy.yaml\`):
9953
10226
 
9954
10227
  | Role | Mission (summary) |
9955
10228
  | :--- | :--- |
9956
- | \`agent-product-analyst\` | ProductShape artifacts (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`); \`status\` starts \`draft\`. |
10229
+ | \`agent-product-analyst\` | Phase 0 NAF v4 Enterprise & Capability Vision (\`ARCH-INTRO-*\`, 3\u20135 question interview) + ProductShape artifacts (\`ACT-*\`, \`UC-*\`, \`FR-*\`, \`QR-*\`, \`BR-*\`); \`status\` starts \`draft\`. |
9957
10230
  | \`agent-threat-modeler\` | STRIDE/OWASP threat triad (\`ACT-THREAT-*\`, \`ABUSE-*\`, \`SEC-REQ-*\`). |
9958
10231
  | \`agent-system-architect\` | Modular arc42 + NAF v4 architecture (\`CMP-*\`, Mermaid diagrams, \`ADR-*\`). |
9959
10232
  | \`agent-qa-engineer\` | FAILING BDD/Gherkin suites before \`agent-developer\` writes production code. |
@@ -10761,7 +11034,7 @@ var ALL_ARCHITECTURE_TEMPLATES = [
10761
11034
  { filename: "cross-cutting-concepts.template.md", content: STARTER_ARCH_CROSS_CUTTING_CONCEPTS, isMinimal: false },
10762
11035
  { filename: "deployment-view.template.md", content: STARTER_ARCH_DEPLOYMENT_VIEW, isMinimal: false },
10763
11036
  { filename: "glossary.template.md", content: STARTER_ARCH_GLOSSARY, isMinimal: false },
10764
- { filename: "introduction-and-goals.template.md", content: STARTER_ARCH_INTRODUCTION_AND_GOALS, isMinimal: false },
11037
+ { filename: "introduction-and-goals.template.md", content: STARTER_ARCH_INTRODUCTION_AND_GOALS, isMinimal: true },
10765
11038
  { filename: "level-1-whitebox.template.md", content: STARTER_ARCH_LEVEL_1_WHITEBOX, isMinimal: false },
10766
11039
  { filename: "quality-requirements.template.md", content: STARTER_ARCH_QUALITY_REQUIREMENTS, isMinimal: false },
10767
11040
  { filename: "risks-and-technical-debt.template.md", content: STARTER_ARCH_RISKS_AND_TECHNICAL_DEBT, isMinimal: false },