@specatlas/core 0.1.6 → 0.1.8

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  signApproval
3
- } from "./chunk-2BFXQ65Q.js";
3
+ } from "./chunk-LMJURGRU.js";
4
4
  import "./chunk-5RKNY2ZC.js";
5
5
  export {
6
6
  signApproval
@@ -78,6 +78,7 @@ var changeMetaSchema = z.object({
78
78
  risk: z.enum(["low", "medium", "high"]).optional(),
79
79
  created: z.string().optional(),
80
80
  owner: z.string().optional(),
81
+ mockups: z.enum(["required", "skip"]).optional(),
81
82
  tracker: z.object({ provider: z.string(), id: z.string() }).optional(),
82
83
  paused: z.object({ reason: z.string(), at: z.string(), by: z.string() }).optional(),
83
84
  lane_history: z.array(z.object({ from: z.enum(["fix", "standard", "full"]), to: z.enum(["fix", "standard", "full"]), at: z.string(), by: z.string() })).optional(),
@@ -107,6 +108,7 @@ function parseChangeMeta(raw, filePath) {
107
108
  if (v.risk !== void 0) meta.risk = v.risk;
108
109
  if (v.created !== void 0) meta.created = v.created;
109
110
  if (v.owner !== void 0) meta.owner = v.owner;
111
+ if (v.mockups !== void 0) meta.mockups = v.mockups;
110
112
  if (v.tracker !== void 0) meta.tracker = v.tracker;
111
113
  if (v.paused !== void 0) meta.paused = v.paused;
112
114
  if (v.lane_history !== void 0) meta.laneHistory = v.lane_history;
package/dist/index.d.ts CHANGED
@@ -143,6 +143,7 @@ interface ChangeMeta {
143
143
  risk?: RiskLevel;
144
144
  created?: string;
145
145
  owner?: string;
146
+ mockups?: 'required' | 'skip';
146
147
  tracker?: {
147
148
  provider: string;
148
149
  id: string;
@@ -618,6 +619,7 @@ declare const changeMetaSchema: z.ZodObject<{
618
619
  risk: z.ZodOptional<z.ZodEnum<["low", "medium", "high"]>>;
619
620
  created: z.ZodOptional<z.ZodString>;
620
621
  owner: z.ZodOptional<z.ZodString>;
622
+ mockups: z.ZodOptional<z.ZodEnum<["required", "skip"]>>;
621
623
  tracker: z.ZodOptional<z.ZodObject<{
622
624
  provider: z.ZodString;
623
625
  id: z.ZodString;
@@ -682,6 +684,7 @@ declare const changeMetaSchema: z.ZodObject<{
682
684
  id: string;
683
685
  provider: string;
684
686
  } | undefined;
687
+ mockups?: "required" | "skip" | undefined;
685
688
  domain?: string | undefined;
686
689
  title?: string | undefined;
687
690
  risk?: "low" | "medium" | "high" | undefined;
@@ -712,6 +715,7 @@ declare const changeMetaSchema: z.ZodObject<{
712
715
  provider: string;
713
716
  } | undefined;
714
717
  schema_version?: number | undefined;
718
+ mockups?: "required" | "skip" | undefined;
715
719
  domain?: string | undefined;
716
720
  title?: string | undefined;
717
721
  lane?: "fix" | "standard" | "full" | undefined;
@@ -860,7 +864,7 @@ declare function planWaves(tasks: TasksFile, opts?: {
860
864
  }): WavePlan;
861
865
  declare function planBlock(block: TaskBlock, maxParallel: number): BlockWavePlan;
862
866
 
863
- type ChangeState = 'draft' | 'spec_draft' | 'awaiting_approval' | 'approved' | 'planned' | 'building' | 'built' | 'verified' | 'ready' | 'archived';
867
+ type ChangeState = 'draft' | 'spec_draft' | 'awaiting_mockups' | 'awaiting_approval' | 'approved' | 'planned' | 'building' | 'built' | 'verified' | 'ready' | 'archived';
864
868
  interface NextAction {
865
869
  command: string;
866
870
  description: string;
@@ -892,8 +896,10 @@ interface DeriveInput {
892
896
  cfg: AtlasConfig;
893
897
  approval: ApprovalStatus;
894
898
  blockingFindings: number;
899
+ mockupsReady?: boolean;
895
900
  specContent?: string;
896
901
  }
902
+ declare function requiresMockups(meta: ChangeMeta | undefined, cfg: AtlasConfig): boolean;
897
903
  declare function deriveState(input: DeriveInput): DerivedState;
898
904
  declare function stateLabel(state: ChangeState): string;
899
905
 
@@ -1553,6 +1559,10 @@ interface CaptureResult {
1553
1559
  diagnostics: Diagnostic[];
1554
1560
  }
1555
1561
  declare function captureMockups(root: string, slug: string, manifest: MockupManifest, now?: Date): Promise<CaptureResult>;
1562
+ declare function mockupsReady(root: string, slug: string, change: Change): Promise<boolean>;
1563
+ declare function setMockupRequirement(root: string, slug: string, value: 'required' | 'skip'): Promise<{
1564
+ path: string;
1565
+ }>;
1556
1566
 
1557
1567
  interface AdoptOptions {
1558
1568
  root: string;
@@ -1684,4 +1694,4 @@ declare function livingRequirementsMap(specs: Array<{
1684
1694
  }>): Map<string, Requirement>;
1685
1695
  declare function runCiGate(opts: CiOptions): Promise<CiResult>;
1686
1696
 
1687
- export { type AdoptDomain, type AdoptOptions, type AdoptResult, type AgingBucket, type AnalyzeOptions, type AnalyzePackSummary, type AnalyzeResult, type Approval, type ApprovalStatus, type ApprovalsFile, type ApprovalsIndex, type ApproveFromGithubOptions, type ApproveFromGithubResult, type ArchiveOptions, type ArchiveResult, type AtlasConfig, type AttentionItem, BLOCK_HEAD_RE, BUILTIN_PACKS, type BlockWavePlan, CONFIG_FILE, CORE_VERSION, type CaptureResult, type Change, type ChangeMeta, type ChangeMetrics, type ChangeState, type CiCheck, type CiExtraCheck, type CiOptions, type CiResult, type Delta, type DeltaOp, type DeriveInput, type DerivedState, type DetectionResult, type Diagnostic, type DoctorReport, type Domain, type Evidence, type EvidenceMethod, type EvidenceResult, type ExecOptions, type ExecResult, type FoldOutcome, type FrontmatterResult, type GhRunner, type GitHubRepo, type InitOptions, type InitResult, type IssueBodyInput, type Lane, type Language, type LinkedIssue, type LintOptions, type LoadedConfig, type MockupCheckResult, type MockupManifest, type MockupPlan, type MockupPlanScreen, type MockupScreen, type NewChangeOptions, type NewChangeResult, type NextAction, type Override, type Pack, type PackCheck, type PackCheckResult, type PackCheckType, type PackEvaluation, type PresentOptions, type PresentResult, type ProfileMatch, REQ_HEAD_RE, REQ_ID_RE, RULE_ID_RE, RULE_RE, RUN_EVENT_TYPES, type RecordEvidenceOptions, type RecordEvidenceResult, type Rename, type Requirement, type RiskLevel, type Rule, type RunEvent, type RunEventType, type RunRecord, type RunState, type RunStatus, SCENARIO_HEAD_RE, SCENARIO_ID_RE, SDD_DIR, SLUG_RE, type Scenario, type Severity, type SignApprovalOptions, type SignApprovalResult, type SpecFile, type SpecRef, type StackProfile, type SyncGithubOptions, type SyncGithubResult, TASK_ID_RE, TASK_LINE_RE, type Task, type TaskBlock, type TasksFile, type TemplateSet, type TraceEdge, type TraceFinding, type TraceGraph, type TraceInput, type TraceNode, type TraceResult, type VerifyFile, type WalkEntry, type WavePlan, type Workspace, type WorkspaceMetrics, adoptWorkspace, appendRunEvent, approvalsSchema, approveFromGithub, archiveChange, artifactHash, atlasConfigSchema, buildTraceGraph, canonicalizeMarkdown, captureMockups, changeMarker, changeMetaSchema, changeMetaYaml, checkMockups, checkTrace, collectMetrics, commentIssue, compareTaskIds, computeInputsHash, configToYaml, copyFile, countBySeverity, createChange, createIssue, createRun, defaultConfig, deriveState, detectProfiles, detectRepo, detectionToYaml, diag, editIssue, emitFrontmatter, ensureDir, ensureSddDirs, esc, evaluatePacks, evidenceSummary, exists, findLinkedIssue, findWorkspaceRoot, firstToken, foldDelta, generatePresentation, generateRunId, getNumber, getString, ghAuthStatus, ghAvailable, hasErrors, hasShellMetacharacters, indexMarkdown, initWorkspace, inline, isCommandAllowed, isDirectory, issueBody, issueLabels, laneOrDefault, lintDelta, lintMockupHtml, lintMockupManifest, lintRequirement, lintSpec, lintTasks, lintVerify, listChangeSlugs, listDir, listDirs, listRuns, livingRequirementsMap, loadActiveProfile, loadApprovals, loadChange, loadConfig, loadDetectedBest, loadProfileFile, loadProfilesFromDir, loadProjectPacks, loadSpecs, loadWorkspace, matchGlob, mockupManifestSchema, mockupsDir, packFindings, parseApprovals, parseChangeMeta, parseConfig, parseDelta, parseFrontmatter, parseGitHubRemote, parseIssueUrl, parseRequirementBlocks, parseSpecFile, parseTasksFile, parseVerifyFile, patchChangeMeta, planBlock, planMockups, planWaves, profileSchema, readMockupManifest, readRun, readText, readTextIfExists, recordEvidence, regenerateIndex, renderMarkdown, renderRequirement, renderTemplate, resolvePacks, runAnalyze, runCiGate, runDoctor, runProcess, sha256, shortHash, signApproval, specHashOf, splitCommand, stateLabel, syncGithubIssue, templatesFor, toPosix, tokensFile, updateMockupScreenshots, updateRunStatus, verifyApproval, walkFiles, writeConfig, writeMockupManifest, writeMockupPlan, writeText };
1697
+ export { type AdoptDomain, type AdoptOptions, type AdoptResult, type AgingBucket, type AnalyzeOptions, type AnalyzePackSummary, type AnalyzeResult, type Approval, type ApprovalStatus, type ApprovalsFile, type ApprovalsIndex, type ApproveFromGithubOptions, type ApproveFromGithubResult, type ArchiveOptions, type ArchiveResult, type AtlasConfig, type AttentionItem, BLOCK_HEAD_RE, BUILTIN_PACKS, type BlockWavePlan, CONFIG_FILE, CORE_VERSION, type CaptureResult, type Change, type ChangeMeta, type ChangeMetrics, type ChangeState, type CiCheck, type CiExtraCheck, type CiOptions, type CiResult, type Delta, type DeltaOp, type DeriveInput, type DerivedState, type DetectionResult, type Diagnostic, type DoctorReport, type Domain, type Evidence, type EvidenceMethod, type EvidenceResult, type ExecOptions, type ExecResult, type FoldOutcome, type FrontmatterResult, type GhRunner, type GitHubRepo, type InitOptions, type InitResult, type IssueBodyInput, type Lane, type Language, type LinkedIssue, type LintOptions, type LoadedConfig, type MockupCheckResult, type MockupManifest, type MockupPlan, type MockupPlanScreen, type MockupScreen, type NewChangeOptions, type NewChangeResult, type NextAction, type Override, type Pack, type PackCheck, type PackCheckResult, type PackCheckType, type PackEvaluation, type PresentOptions, type PresentResult, type ProfileMatch, REQ_HEAD_RE, REQ_ID_RE, RULE_ID_RE, RULE_RE, RUN_EVENT_TYPES, type RecordEvidenceOptions, type RecordEvidenceResult, type Rename, type Requirement, type RiskLevel, type Rule, type RunEvent, type RunEventType, type RunRecord, type RunState, type RunStatus, SCENARIO_HEAD_RE, SCENARIO_ID_RE, SDD_DIR, SLUG_RE, type Scenario, type Severity, type SignApprovalOptions, type SignApprovalResult, type SpecFile, type SpecRef, type StackProfile, type SyncGithubOptions, type SyncGithubResult, TASK_ID_RE, TASK_LINE_RE, type Task, type TaskBlock, type TasksFile, type TemplateSet, type TraceEdge, type TraceFinding, type TraceGraph, type TraceInput, type TraceNode, type TraceResult, type VerifyFile, type WalkEntry, type WavePlan, type Workspace, type WorkspaceMetrics, adoptWorkspace, appendRunEvent, approvalsSchema, approveFromGithub, archiveChange, artifactHash, atlasConfigSchema, buildTraceGraph, canonicalizeMarkdown, captureMockups, changeMarker, changeMetaSchema, changeMetaYaml, checkMockups, checkTrace, collectMetrics, commentIssue, compareTaskIds, computeInputsHash, configToYaml, copyFile, countBySeverity, createChange, createIssue, createRun, defaultConfig, deriveState, detectProfiles, detectRepo, detectionToYaml, diag, editIssue, emitFrontmatter, ensureDir, ensureSddDirs, esc, evaluatePacks, evidenceSummary, exists, findLinkedIssue, findWorkspaceRoot, firstToken, foldDelta, generatePresentation, generateRunId, getNumber, getString, ghAuthStatus, ghAvailable, hasErrors, hasShellMetacharacters, indexMarkdown, initWorkspace, inline, isCommandAllowed, isDirectory, issueBody, issueLabels, laneOrDefault, lintDelta, lintMockupHtml, lintMockupManifest, lintRequirement, lintSpec, lintTasks, lintVerify, listChangeSlugs, listDir, listDirs, listRuns, livingRequirementsMap, loadActiveProfile, loadApprovals, loadChange, loadConfig, loadDetectedBest, loadProfileFile, loadProfilesFromDir, loadProjectPacks, loadSpecs, loadWorkspace, matchGlob, mockupManifestSchema, mockupsDir, mockupsReady, packFindings, parseApprovals, parseChangeMeta, parseConfig, parseDelta, parseFrontmatter, parseGitHubRemote, parseIssueUrl, parseRequirementBlocks, parseSpecFile, parseTasksFile, parseVerifyFile, patchChangeMeta, planBlock, planMockups, planWaves, profileSchema, readMockupManifest, readRun, readText, readTextIfExists, recordEvidence, regenerateIndex, renderMarkdown, renderRequirement, renderTemplate, requiresMockups, resolvePacks, runAnalyze, runCiGate, runDoctor, runProcess, setMockupRequirement, sha256, shortHash, signApproval, specHashOf, splitCommand, stateLabel, syncGithubIssue, templatesFor, toPosix, tokensFile, updateMockupScreenshots, updateRunStatus, verifyApproval, walkFiles, writeConfig, writeMockupManifest, writeMockupPlan, writeText };
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  sha256,
12
12
  shortHash,
13
13
  signApproval
14
- } from "./chunk-2BFXQ65Q.js";
14
+ } from "./chunk-LMJURGRU.js";
15
15
  import {
16
16
  copyFile,
17
17
  ensureDir,
@@ -1008,6 +1008,14 @@ function verifyApproval(change, approvals, cfg, specContent) {
1008
1008
  if (current !== approval.hash) return { status: "stale", approvedBy: approval.by, approvedAt: approval.at };
1009
1009
  return { status: "valid", approvedBy: approval.by, approvedAt: approval.at };
1010
1010
  }
1011
+ function requiresMockups(meta, cfg) {
1012
+ if (meta?.mockups === "required") return true;
1013
+ if (meta?.mockups === "skip") return false;
1014
+ return cfg.gates.mockup.require_approval;
1015
+ }
1016
+ function mockupOverride(change) {
1017
+ return (change.meta?.overrides ?? []).some((override) => override.gate === "mockup");
1018
+ }
1011
1019
  function deriveState(input) {
1012
1020
  const { change, cfg, approval, blockingFindings } = input;
1013
1021
  const lane = change.meta?.lane ?? cfg.lanes.default;
@@ -1040,6 +1048,14 @@ function deriveState(input) {
1040
1048
  blockedBy.push(`${blockingFindings} hallazgo(s) bloqueante(s)`);
1041
1049
  return { state: "spec_draft", blockedBy, nextAction: next(`satlas validate --change ${change.slug}`, "Corregir los hallazgos de la especificaci\xF3n"), progress };
1042
1050
  }
1051
+ if ((approval.status === "missing" || approval.status === "stale") && requiresMockups(change.meta, cfg) && input.mockupsReady !== true && !mockupOverride(change)) {
1052
+ return {
1053
+ state: "awaiting_mockups",
1054
+ blockedBy: ["mockups requeridos y no listos"],
1055
+ nextAction: next(`/satlas-mockup ${change.slug}`, "Generar los mockups (contrato visual) antes de aprobar", true),
1056
+ progress
1057
+ };
1058
+ }
1043
1059
  if (approval.status === "missing" || approval.status === "stale") {
1044
1060
  blockedBy.push(approval.status === "stale" ? "la firma de la spec qued\xF3 obsoleta (el archivo cambi\xF3)" : "la spec no est\xE1 aprobada");
1045
1061
  const presented = change.presentationPath !== void 0;
@@ -1070,6 +1086,7 @@ function stateLabel(state) {
1070
1086
  const labels = {
1071
1087
  draft: "borrador",
1072
1088
  spec_draft: "spec en borrador",
1089
+ awaiting_mockups: "esperando mockups",
1073
1090
  awaiting_approval: "esperando aprobaci\xF3n",
1074
1091
  approved: "aprobado",
1075
1092
  planned: "planificado",
@@ -1653,6 +1670,7 @@ function changeMetaYaml(meta) {
1653
1670
  if (meta.risk) doc["risk"] = meta.risk;
1654
1671
  if (meta.created) doc["created"] = meta.created;
1655
1672
  if (meta.owner) doc["owner"] = meta.owner;
1673
+ if (meta.mockups) doc["mockups"] = meta.mockups;
1656
1674
  return `# Estado del cambio. La fase se DERIVA de los artefactos; aqu\xED solo hechos.
1657
1675
  ` + stringifyYaml3(doc, { lineWidth: 120 });
1658
1676
  }
@@ -1951,7 +1969,7 @@ async function approveFromGithub(opts) {
1951
1969
  if (!by) {
1952
1970
  return { approved: false, label, issueNumber: number, diagnostics: [diag("ATLAS-GH-011", "error", "No se pudo determinar qui\xE9n aprueba (--by ni `gh api user`)")] };
1953
1971
  }
1954
- const { signApproval: signApproval2 } = await import("./approvals-HCBC7QDM.js");
1972
+ const { signApproval: signApproval2 } = await import("./approvals-4QHIT7F6.js");
1955
1973
  const signed = await signApproval2({
1956
1974
  root: opts.root,
1957
1975
  artifact: path5.posix.join("changes", opts.slug, "spec.md"),
@@ -2514,6 +2532,28 @@ async function captureMockups(root, slug, manifest, now = /* @__PURE__ */ new Da
2514
2532
  void now;
2515
2533
  return { screenshots, diagnostics };
2516
2534
  }
2535
+ async function mockupsReady(root, slug, change) {
2536
+ const check = await checkMockups(root, slug, change);
2537
+ return Boolean(check.manifest && check.manifest.screens.length > 0 && !check.stale);
2538
+ }
2539
+ async function setMockupRequirement(root, slug, value) {
2540
+ const file = path8.join(root, ".sdd", "changes", slug, "meta.yaml");
2541
+ const raw = await readTextIfExists(file) ?? `schema_version: 1
2542
+ slug: ${slug}
2543
+ lane: standard
2544
+ `;
2545
+ const lines = raw.replace(/\r\n?/g, "\n").split("\n");
2546
+ const index = lines.findIndex((line) => /^mockups:/.test(line));
2547
+ if (index >= 0) {
2548
+ lines[index] = `mockups: ${value}`;
2549
+ } else {
2550
+ let last = lines.length;
2551
+ while (last > 0 && (lines[last - 1] ?? "").trim() === "") last -= 1;
2552
+ lines.splice(last, 0, `mockups: ${value}`);
2553
+ }
2554
+ await writeText(file, lines.join("\n"));
2555
+ return { path: file };
2556
+ }
2517
2557
 
2518
2558
  // src/packs.ts
2519
2559
  import path9 from "path";
@@ -3080,6 +3120,8 @@ async function generatePresentation(opts) {
3080
3120
  const mockupInfo = await copyMockups(root, change, mockupsCopyDir);
3081
3121
  const proposalRaw = await readTextIfExists(path12.join(change.dir, "proposal.md"));
3082
3122
  const proposalBody = proposalRaw ? parseFrontmatter(proposalRaw).body : "";
3123
+ const approvals = await loadApprovals(path12.join(root, ".sdd"));
3124
+ const approval = verifyApproval(change, approvals.byArtifact, config, deltaContent);
3083
3125
  const labels = labelsFor(language);
3084
3126
  const html = page({
3085
3127
  language,
@@ -3096,7 +3138,8 @@ async function generatePresentation(opts) {
3096
3138
  evidence: new Map((change.verify?.evidence ?? []).map((e) => [e.scenario, e.result])),
3097
3139
  mockups: mockupInfo.screens,
3098
3140
  screenshots: mockupInfo.screenshots,
3099
- approveHint: `satlas approve ${change.slug} --by "<nombre>" --channel presentation`
3141
+ approveHint: `satlas approve ${change.slug} --by "<nombre>" --channel presentation`,
3142
+ ...approval.status === "valid" && approval.approvedBy ? { approval: { by: approval.approvedBy, at: approval.approvedAt ?? "" } } : {}
3100
3143
  });
3101
3144
  const outFile = path12.join(presentationDir, "index.html");
3102
3145
  await writeText(outFile, html);
@@ -3147,6 +3190,7 @@ function labelsFor(language) {
3147
3190
  mockups: "Mockups",
3148
3191
  approve: "Approval",
3149
3192
  approveText: "This proposal is approved by signing the spec (hash + author). Any later change invalidates the signature.",
3193
+ approveDone: "Approved by {by} on {at}. Any later change invalidates the signature.",
3150
3194
  command: "Command",
3151
3195
  hash: "Hash",
3152
3196
  generated: "Generated",
@@ -3168,6 +3212,7 @@ function labelsFor(language) {
3168
3212
  mockups: "Mockups",
3169
3213
  approve: "Aprobaci\xF3n",
3170
3214
  approveText: "Esta propuesta se aprueba firmando la spec (hash + autor). Cualquier cambio posterior invalida la firma.",
3215
+ approveDone: "Aprobada por {by} el {at}. Cualquier cambio posterior invalida la firma.",
3171
3216
  command: "Comando",
3172
3217
  hash: "Hash",
3173
3218
  generated: "Generado",
@@ -3283,8 +3328,8 @@ function page(input) {
3283
3328
 
3284
3329
  <section>
3285
3330
  <h2>${esc(l.approve)}</h2>
3286
- <div class="callout">${esc(l.approveText)}</div>
3287
- <p>${esc(l.command)}: <code>${esc(input.approveHint)}</code></p>
3331
+ ${input.approval ? `<div class="callout" style="border-left-color:#15803d;background:rgba(21,128,61,.12)">\u2714 ${esc(l.approveDone.replace("{by}", input.approval.by).replace("{at}", input.approval.at))}</div>` : `<div class="callout">${esc(l.approveText)}</div>
3332
+ <p>${esc(l.command)}: <code>${esc(input.approveHint)}</code></p>`}
3288
3333
  </section>
3289
3334
 
3290
3335
  <footer>SpecAtlas \xB7 ${esc(input.project)} \xB7 ${esc(input.generatedAt)}</footer>
@@ -4037,6 +4082,7 @@ export {
4037
4082
  matchGlob,
4038
4083
  mockupManifestSchema,
4039
4084
  mockupsDir,
4085
+ mockupsReady,
4040
4086
  packFindings,
4041
4087
  parseApprovals,
4042
4088
  parseChangeMeta,
@@ -4065,11 +4111,13 @@ export {
4065
4111
  renderRequirement,
4066
4112
  renderStyles,
4067
4113
  renderTemplate,
4114
+ requiresMockups,
4068
4115
  resolvePacks,
4069
4116
  runAnalyze,
4070
4117
  runCiGate,
4071
4118
  runDoctor,
4072
4119
  runProcess,
4120
+ setMockupRequirement,
4073
4121
  sha256,
4074
4122
  shortHash,
4075
4123
  signApproval,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specatlas/core",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Kernel determinista de SpecAtlas: parsing, validación, trazabilidad, olas y ciclo de vida",
5
5
  "license": "MIT",
6
6
  "type": "module",