@tacuchi/agent-workflow-cli 20.26.0 → 21.0.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.
Files changed (110) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/node-file-system.js +3 -0
  3. package/dist/adapters/node-file-system.js.map +1 -1
  4. package/dist/application/design/design-gate-service.js +246 -0
  5. package/dist/application/design/design-gate-service.js.map +1 -0
  6. package/dist/application/design/design-graph-service.js +85 -0
  7. package/dist/application/design/design-graph-service.js.map +1 -0
  8. package/dist/application/design/design-index-service.js +132 -0
  9. package/dist/application/design/design-index-service.js.map +1 -0
  10. package/dist/application/design/design-publish-service.js +488 -0
  11. package/dist/application/design/design-publish-service.js.map +1 -0
  12. package/dist/application/design/design-resolver-service.js +165 -0
  13. package/dist/application/design/design-resolver-service.js.map +1 -0
  14. package/dist/application/resume-service.js +23 -4
  15. package/dist/application/resume-service.js.map +1 -1
  16. package/dist/application/semantic-operation/protocol.js +18 -12
  17. package/dist/application/semantic-operation/protocol.js.map +1 -1
  18. package/dist/application/semantic-operation/publish.js +56 -9
  19. package/dist/application/semantic-operation/publish.js.map +1 -1
  20. package/dist/application/skills-resolver-service.js +19 -4
  21. package/dist/application/skills-resolver-service.js.map +1 -1
  22. package/dist/application/status-service.js +1 -0
  23. package/dist/application/status-service.js.map +1 -1
  24. package/dist/application/workline-index-service.js +6 -0
  25. package/dist/application/workline-index-service.js.map +1 -1
  26. package/dist/application/workspace-init-service.js +9 -1
  27. package/dist/application/workspace-init-service.js.map +1 -1
  28. package/dist/cli/commands/designs.js +110 -0
  29. package/dist/cli/commands/designs.js.map +1 -0
  30. package/dist/cli/commands/index.js +2 -0
  31. package/dist/cli/commands/index.js.map +1 -1
  32. package/dist/cli/commands/resume.js +8 -0
  33. package/dist/cli/commands/resume.js.map +1 -1
  34. package/dist/cli/commands/status.js +45 -0
  35. package/dist/cli/commands/status.js.map +1 -1
  36. package/dist/cli/help-groups.js +3 -0
  37. package/dist/cli/help-groups.js.map +1 -1
  38. package/dist/cli/parser.js +1 -0
  39. package/dist/cli/parser.js.map +1 -1
  40. package/dist/domain/design/artifact-body.js +223 -0
  41. package/dist/domain/design/artifact-body.js.map +1 -0
  42. package/dist/domain/design/artifact.js +606 -0
  43. package/dist/domain/design/artifact.js.map +1 -0
  44. package/dist/domain/design/baseline.js +359 -0
  45. package/dist/domain/design/baseline.js.map +1 -0
  46. package/dist/domain/design/capability.js +51 -0
  47. package/dist/domain/design/capability.js.map +1 -0
  48. package/dist/domain/design/closure.js +161 -0
  49. package/dist/domain/design/closure.js.map +1 -0
  50. package/dist/domain/design/governance.js +298 -0
  51. package/dist/domain/design/governance.js.map +1 -0
  52. package/dist/domain/design/identity.js +145 -0
  53. package/dist/domain/design/identity.js.map +1 -0
  54. package/dist/domain/design/manifest.js +552 -0
  55. package/dist/domain/design/manifest.js.map +1 -0
  56. package/dist/domain/design/maturity.js +234 -0
  57. package/dist/domain/design/maturity.js.map +1 -0
  58. package/dist/domain/design/naming.js +117 -0
  59. package/dist/domain/design/naming.js.map +1 -0
  60. package/dist/domain/design/projections.js +165 -0
  61. package/dist/domain/design/projections.js.map +1 -0
  62. package/dist/domain/design/reference.js +234 -0
  63. package/dist/domain/design/reference.js.map +1 -0
  64. package/dist/domain/design/retired.js +61 -0
  65. package/dist/domain/design/retired.js.map +1 -0
  66. package/dist/domain/design/revision.js +219 -0
  67. package/dist/domain/design/revision.js.map +1 -0
  68. package/dist/domain/design/secrets.js +86 -0
  69. package/dist/domain/design/secrets.js.map +1 -0
  70. package/dist/domain/design/validation.js +75 -0
  71. package/dist/domain/design/validation.js.map +1 -0
  72. package/dist/domain/design/yaml-subset.js +390 -0
  73. package/dist/domain/design/yaml-subset.js.map +1 -0
  74. package/dist/domain/safe-path.js +23 -0
  75. package/dist/domain/safe-path.js.map +1 -0
  76. package/dist/domain/skills.js +27 -3
  77. package/dist/domain/skills.js.map +1 -1
  78. package/package.json +1 -1
  79. package/skills/w/SKILL.md +10 -8
  80. package/skills/w/artifacts/README.md +3 -4
  81. package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +2 -2
  82. package/skills/w/commands/plan-exec.md +11 -5
  83. package/skills/w/commands/plan-new.md +6 -2
  84. package/skills/w/commands/plan-refine.md +6 -3
  85. package/skills/w/commands/quick.md +2 -2
  86. package/skills/w/commands/spec-new.md +2 -2
  87. package/skills/w/commands/spec-refine.md +1 -0
  88. package/skills/w/context/MANIFEST.json +19 -8
  89. package/skills/w/loops/CHASSIS.md +2 -2
  90. package/skills/w/loops/CODE-POLICIES.md +22 -7
  91. package/skills/w/loops/README.md +1 -1
  92. package/skills/w/loops/plan-exec-loop/LOOP.md +127 -61
  93. package/skills/w/loops/plan-new-loop/LOOP.md +66 -70
  94. package/skills/w/loops/plan-refine-loop/LOOP.md +15 -7
  95. package/skills/w/loops/spec-refine-loop/LOOP.md +14 -12
  96. package/skills/w/modules/DESIGN-REFERENCES.md +109 -0
  97. package/skills/w/modules/PERSIST-ROUTING.md +1 -0
  98. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +84 -0
  99. package/skills/w/roles/README.md +7 -5
  100. package/skills/w/roles/design/ROLE.md +217 -0
  101. package/skills/w/schemas/design/design-baseline.v1.schema.json +71 -0
  102. package/skills/w/schemas/design/design-manifest.v1.schema.json +322 -0
  103. package/skills/w/schemas/design/design-review.v1.schema.json +72 -0
  104. package/skills/w/schemas/design/design-revocation.v1.schema.json +54 -0
  105. package/skills/w/schemas/design/ui-flow.v1.schema.json +211 -0
  106. package/skills/w/schemas/design/ui-screen.v1.schema.json +214 -0
  107. package/skills/w/artifacts/artifacts-design/SPEC.md +0 -42
  108. package/skills/w/modules/PLAN-DESIGN-SPECS.md +0 -12
  109. package/skills/w/modules/PLAN-REFINE-DESIGN-SPECS.md +0 -7
  110. package/skills/w/roles/ui-spec/ROLE.md +0 -147
@@ -0,0 +1,234 @@
1
+ import { ESSENTIAL_HEADINGS, HEADINGS, conditionalKeys, headingKey, parseBody, } from "./artifact-body.js";
2
+ import { splitDesignDocument, validateDesignArtifact, } from "./artifact.js";
3
+ import { parseArtifactId, parseArtifactRef } from "./identity.js";
4
+ /**
5
+ * A reference that is only a picture. A rendition shows what a screen LOOKED
6
+ * like when someone rendered it; it is not the semantics and it is not a WCAG
7
+ * verdict. A section whose entire content is a rendition reference has answered
8
+ * with an image (AC-SEM-07).
9
+ */
10
+ const RENDITION_ONLY = /^(?:\s*(?:DES-[0-9]+\/)?VIS-[0-9]+@r[0-9]+\s*[,·.;]?\s*)+$/;
11
+ /** Sections whose closure a `handoff` must be able to demonstrate later. */
12
+ const OBLIGATION_KEYS = new Set([
13
+ "accessibility",
14
+ "data_permissions_and_validation",
15
+ "states_and_transitions",
16
+ "responsive_and_adaptation",
17
+ "localization",
18
+ "permissions_and_privacy",
19
+ "alternatives_and_recovery",
20
+ ]);
21
+ export function checkMaturity(artifact, sections, kind, file) {
22
+ const obligations = readObligations(sections, artifact.not_applicable);
23
+ const failures = [
24
+ ...checkOutlineFloor(artifact, sections, kind, file),
25
+ ...(artifact.maturity === "handoff" ? checkHandoff(artifact, sections, kind, file) : []),
26
+ ];
27
+ return {
28
+ attainable: failures.length === 0 ? artifact.maturity : "outline",
29
+ failures,
30
+ obligations,
31
+ };
32
+ }
33
+ /**
34
+ * The floor BOTH profiles stand on (AC-SEM-01).
35
+ *
36
+ * `outline` is not "anything goes": it is the minimum inventory from which the
37
+ * next revision can be planned — who, what for, on what, what screens or steps
38
+ * exist, and what it traces to. What `outline` does NOT demand is completing the
39
+ * handoff early, which is why every check here is about presence, not depth.
40
+ */
41
+ function checkOutlineFloor(artifact, sections, kind, file) {
42
+ const failures = [];
43
+ if (artifact.trace.length === 0) {
44
+ failures.push({
45
+ code: "DESIGN_MATURITY_INCOMPLETE",
46
+ artifact: file,
47
+ message: "sin trazabilidad no hay inventario: 'trace' está vacío",
48
+ action: "declará al menos el Requirement y el acceptance criterion que origina esto",
49
+ });
50
+ }
51
+ if (artifact.kind === "flow" && artifact.actors.length === 0) {
52
+ failures.push({
53
+ code: "DESIGN_MATURITY_INCOMPLETE",
54
+ artifact: file,
55
+ message: "no declara actores: el inventario mínimo incluye quién lo recorre",
56
+ action: "declará al menos un actor en 'actors'",
57
+ });
58
+ }
59
+ const inventory = artifact.kind === "flow"
60
+ ? { what: "nodos", empty: artifact.nodes.length === 0 }
61
+ : { what: "estados", empty: artifact.states.length === 0 };
62
+ if (inventory.empty) {
63
+ failures.push({
64
+ code: "DESIGN_MATURITY_INCOMPLETE",
65
+ artifact: file,
66
+ message: `el inventario mínimo está vacío: no declara ${inventory.what}`,
67
+ action: `un ${kind} en 'outline' ya enumera sus ${inventory.what}, aunque no los detalle`,
68
+ });
69
+ }
70
+ // Acá vivía un cruce `unknown` ↔ `not_applicable` por coincidencia de texto.
71
+ // Era inseguro en las dos direcciones —no veía la contradicción real escrita
72
+ // como pregunta, y bloqueaba documentos legítimos que nombraban la sección de
73
+ // paso— así que se fue: adivinar sobre prosa libre no es una guarda. Lo que
74
+ // AC-SEM-04 exige de verdad lo hace `checkBlockingUnknowns`, sobre un booleano
75
+ // que el autor declara.
76
+ failures.push(...checkPlaceholders(sections, kind, file));
77
+ return failures;
78
+ }
79
+ /** Whatever a section says, it cannot be only a picture — in either profile. */
80
+ function checkPlaceholders(sections, kind, file) {
81
+ const essential = new Set(ESSENTIAL_HEADINGS[kind]);
82
+ return sections
83
+ .filter((s) => essential.has(s.heading) && RENDITION_ONLY.test(s.prose.trim()))
84
+ .map((s) => ({
85
+ code: "DESIGN_EVIDENCE_INSUFFICIENT",
86
+ artifact: file,
87
+ message: `'${s.heading}' responde con una rendition y nada más`,
88
+ action: "una imagen aprobada no es la semántica vigente ni una conformidad WCAG: escribí lo que exige",
89
+ }));
90
+ }
91
+ /**
92
+ * `handoff` (AC-SEM-02, AC-SEM-03, AC-SEM-04, AC-PKG-09).
93
+ *
94
+ * The claim is: everything applicable is closed, and nothing open can still move
95
+ * behavior or acceptance. Every check below is a way that claim can be false.
96
+ */
97
+ function checkHandoff(artifact, sections, kind, file) {
98
+ return [
99
+ ...checkBlockingUnknowns(artifact, file),
100
+ ...checkGraph(artifact, file),
101
+ ...checkApplicableCompleteness(artifact, sections, kind, file),
102
+ ...checkExternalCustody(artifact, file),
103
+ ];
104
+ }
105
+ /**
106
+ * AC-SEM-02: a `handoff` flow states its TRANSITIONS, not just its steps.
107
+ *
108
+ * A flow with two or more nodes and no edges has its graph only in the prose of
109
+ * `## Main journey` — which is exactly what the machine-readable frontmatter
110
+ * exists to avoid. One node and no edges is a legitimate degenerate case.
111
+ */
112
+ function checkGraph(artifact, file) {
113
+ if (artifact.kind !== "flow" || artifact.nodes.length < 2 || artifact.edges.length > 0) {
114
+ return [];
115
+ }
116
+ return [
117
+ {
118
+ code: "DESIGN_MATURITY_INCOMPLETE",
119
+ artifact: file,
120
+ message: `declara ${artifact.nodes.length} nodos y ninguna transición entre ellos`,
121
+ action: "un 'handoff' resuelve su grafo sin interpretar prosa: declará las aristas en 'edges'",
122
+ },
123
+ ];
124
+ }
125
+ /** AC-SEM-04: an open question that can move behavior forbids the claim. */
126
+ function checkBlockingUnknowns(artifact, file) {
127
+ return artifact.unknowns
128
+ .filter((u) => u.blocking)
129
+ .map((u) => ({
130
+ code: "DESIGN_MATURITY_BLOCKED",
131
+ artifact: file,
132
+ message: `queda una incógnita bloqueante: "${u.question}"`,
133
+ action: "resolvela y volvé a declarar 'handoff', o bajá a 'outline': una incógnita no es un 'no aplica'",
134
+ }));
135
+ }
136
+ /**
137
+ * Every section either SAYS something or is justified as inapplicable.
138
+ *
139
+ * The essential sections admit neither escape — F2 already rejects a
140
+ * `not_applicable` on them — so what is left to check here is the conditional
141
+ * ones: silence is not closure.
142
+ */
143
+ function checkApplicableCompleteness(artifact, sections, kind, file) {
144
+ const byKey = new Map(sections.map((s) => [s.key, s]));
145
+ const failures = [];
146
+ for (const key of conditionalKeys(kind)) {
147
+ const waived = artifact.not_applicable[key];
148
+ if (waived !== undefined)
149
+ continue;
150
+ const section = byKey.get(key);
151
+ if (section === undefined || section.text.trim().length > 0)
152
+ continue;
153
+ failures.push({
154
+ code: "DESIGN_MATURITY_INCOMPLETE",
155
+ artifact: file,
156
+ message: `'${headingOf(kind, key)}' está vacía y no se declaró no aplicable`,
157
+ action: `completala, o declará not_applicable.${key} con su razón`,
158
+ });
159
+ }
160
+ return failures;
161
+ }
162
+ /**
163
+ * AC-PKG-09: depending on someone else's design system.
164
+ *
165
+ * A `handoff` that points at another package's rules or tokens is implementable
166
+ * only if that material is HERE — pinned by provider, revision and digest, and
167
+ * kept locally. Otherwise the artifact describes something that can change
168
+ * underneath it, which is exactly what `outline` is for.
169
+ */
170
+ function checkExternalCustody(artifact, file) {
171
+ const own = parseArtifactId(artifact.id)?.package;
172
+ // Todas las referencias, no solo `dependencies`: un flow cuyos NODOS viven en
173
+ // otro package es tan poco implementable como uno cuyas rules viven afuera, y
174
+ // la clausura ya lo declara irresoluble. Las dos mitades tienen que coincidir.
175
+ const refs = artifact.kind === "flow"
176
+ ? [artifact.entry, ...artifact.nodes, ...artifact.dependencies]
177
+ : [...artifact.flow_refs, ...artifact.dependencies.rules, ...artifact.dependencies.tokens];
178
+ const pinned = new Set(artifact.external.map((e) => e.provider));
179
+ const loose = new Map();
180
+ for (const ref of refs) {
181
+ const parsed = parseArtifactRef(ref);
182
+ if (parsed === null || parsed.package === own || pinned.has(parsed.package))
183
+ continue;
184
+ loose.set(parsed.package, [...(loose.get(parsed.package) ?? []), ref]);
185
+ }
186
+ if (loose.size === 0)
187
+ return [];
188
+ return [...loose].map(([provider, refs]) => ({
189
+ code: "DESIGN_EVIDENCE_INSUFFICIENT",
190
+ artifact: file,
191
+ message: `depende de ${provider} sin fijarlo: ${refs.join(", ")}`,
192
+ action: `agregá a 'external' el proveedor ${provider} con su revisión y su digest, y conservá localmente ese subconjunto; sin esa evidencia queda en 'outline'`,
193
+ }));
194
+ }
195
+ /**
196
+ * What the implementation will have to prove.
197
+ *
198
+ * Derived, never authored: the obligations ARE the sections that state demands
199
+ * an implementation can fail — accessibility, permissions, states, adaptation.
200
+ * The gate records them so a later phase can ask for evidence instead of taking
201
+ * a rendered picture as proof.
202
+ *
203
+ * A section the document WAIVED is not an obligation. F2 makes the heading exist
204
+ * with real prose even when it is waived — the machine-readable reason and the
205
+ * human explanation are two audiences — so filtering by prose alone would demand
206
+ * evidence for exactly what the design justified as inapplicable. And the whole
207
+ * section is the statement: cutting at the first period dropped the second half
208
+ * of every rule, which is where the testable part usually lives.
209
+ */
210
+ function readObligations(sections, waived) {
211
+ return sections
212
+ .filter((s) => OBLIGATION_KEYS.has(s.key) && s.prose.trim().length > 0 && waived[s.key] === undefined)
213
+ .map((s) => ({ key: s.key, statement: s.prose.replace(/\s+/g, " ").trim() }));
214
+ }
215
+ function headingOf(kind, key) {
216
+ return HEADINGS[kind].find((h) => headingKey(h) === key) ?? key;
217
+ }
218
+ /**
219
+ * The gate over raw document text: validate, then judge.
220
+ *
221
+ * One entry point so no caller can do half of it. A document that does not
222
+ * validate has no maturity to judge — `attainable` is `outline` because that is
223
+ * the only honest thing to say about text that is not yet a document.
224
+ */
225
+ export function gateDesignDocument(text, kind, file) {
226
+ const document = validateDesignArtifact(text, kind, file);
227
+ if (!document.ok || document.value === null) {
228
+ return { attainable: "outline", failures: document.failures, obligations: [] };
229
+ }
230
+ const split = splitDesignDocument(text);
231
+ const sections = split === null ? [] : parseBody(split.body, split.bodyLine).sections;
232
+ return checkMaturity(document.value, sections, kind, file);
233
+ }
234
+ //# sourceMappingURL=maturity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maturity.js","sourceRoot":"","sources":["../../../src/domain/design/maturity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Where each normative artifact lives, and what its file is called.
3
+ *
4
+ * This is what makes immutability CHECKABLE rather than promised: the revision
5
+ * is part of the file name, so publishing `@r2` writes a new file and cannot
6
+ * overwrite `@r1` — not by policy, but because they are different paths. An
7
+ * asset goes further and carries its own digest, so different bytes can never
8
+ * occupy the same name.
9
+ *
10
+ * The directory layout is contract too (spec § *Package unit and durable
11
+ * location*): `flows/`, `screens/`, `baselines/` and `governance/` always
12
+ * exist; `design-system/`, `renditions/`, `tokens/` and `assets/` appear when
13
+ * the content requires them.
14
+ */
15
+ /** `2` → `r002`. Three digits so a directory listing sorts the way a human reads it. */
16
+ export function revisionSegment(revision) {
17
+ return `r${String(revision).padStart(3, "0")}`;
18
+ }
19
+ export const NAMING = {
20
+ flow: {
21
+ dir: "flows",
22
+ prefix: (id, revision) => `${id}-${revisionSegment(revision)}-`,
23
+ suffix: ".md",
24
+ },
25
+ screen: {
26
+ dir: "screens",
27
+ prefix: (id, revision) => `${id}-${revisionSegment(revision)}-`,
28
+ suffix: ".md",
29
+ },
30
+ rule: {
31
+ dir: "design-system/rules",
32
+ prefix: (id, revision) => `${id}-${revisionSegment(revision)}-`,
33
+ suffix: ".md",
34
+ },
35
+ token: {
36
+ dir: "tokens",
37
+ prefix: (id, revision) => `${id}-${revisionSegment(revision)}-`,
38
+ suffix: ".tokens.json",
39
+ },
40
+ rendition: {
41
+ dir: "renditions",
42
+ prefix: (id, revision) => `${id}-${revisionSegment(revision)}-`,
43
+ suffix: "/rendition.json",
44
+ },
45
+ };
46
+ /** `baselines/DES-001-r004.json` — no slug: a baseline seals a revision, not a name. */
47
+ export function baselinePath(packageId, revision) {
48
+ return `baselines/${packageId}-${revisionSegment(revision)}.json`;
49
+ }
50
+ /**
51
+ * Regenerable projections. They are NOT normative and never appear in the
52
+ * catalog: a baseline that selected them would make its digest depend on
53
+ * something derived, and re-rendering the landing page would rewrite history.
54
+ */
55
+ export const PROJECTIONS = ["PACKAGE.md", "design-system/DESIGN.md"];
56
+ /**
57
+ * Where each governance record lives (T7.1).
58
+ *
59
+ * Separate from `NAMING` on purpose: a record is not a normative artifact, is
60
+ * never selected by a baseline, and has no revision of its own — it decides ON
61
+ * one. Folding it into the same table would hand it a revision segment it must
62
+ * not have.
63
+ */
64
+ export const GOVERNANCE_NAMING = {
65
+ review: { dir: "governance/reviews", prefix: "REV-" },
66
+ revocation: { dir: "governance/revocations", prefix: "RVK-" },
67
+ };
68
+ /** `governance/reviews/REV-001.json`, or why the path does not honor the rule. */
69
+ export function checkGovernanceNaming(kind, path, id) {
70
+ const rule = GOVERNANCE_NAMING[kind];
71
+ const expected = `${rule.dir}/${id}.json`;
72
+ if (path === expected)
73
+ return { ok: true };
74
+ return {
75
+ ok: false,
76
+ why: `'${path}' no es la ubicación de ${id}`,
77
+ expected,
78
+ };
79
+ }
80
+ /** Does `path` name revision `revision` of artifact `id`, in the right place? */
81
+ export function checkNaming(kind, path, id, revision) {
82
+ const rule = NAMING[kind];
83
+ const expected = `${rule.dir}/${rule.prefix(id, revision)}<slug>${rule.suffix}`;
84
+ if (PROJECTIONS.includes(path)) {
85
+ return {
86
+ ok: false,
87
+ why: `'${path}' es una proyección regenerable y no puede catalogarse como artefacto normativo`,
88
+ expected,
89
+ };
90
+ }
91
+ if (!path.startsWith(`${rule.dir}/`)) {
92
+ return { ok: false, why: `'${path}' no vive en '${rule.dir}/'`, expected };
93
+ }
94
+ const rest = path.slice(rule.dir.length + 1);
95
+ if (!rest.startsWith(rule.prefix(id, revision))) {
96
+ // The revision in the name is the whole point: without it, publishing the
97
+ // next revision would write over the one already referenced.
98
+ return {
99
+ ok: false,
100
+ why: `'${path}' no lleva '${rule.prefix(id, revision)}' en el nombre, así que su revisión no está en el path`,
101
+ expected,
102
+ };
103
+ }
104
+ if (!rest.endsWith(rule.suffix)) {
105
+ return { ok: false, why: `'${path}' no termina en '${rule.suffix}'`, expected };
106
+ }
107
+ const slug = rest.slice(rule.prefix(id, revision).length, rest.length - (rule.suffix?.length ?? 0));
108
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(slug)) {
109
+ return {
110
+ ok: false,
111
+ why: `'${slug}' no es un slug: solo minúsculas, números y guiones`,
112
+ expected,
113
+ };
114
+ }
115
+ return { ok: true };
116
+ }
117
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../src/domain/design/naming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ import { PROJECTIONS } from "./naming.js";
2
+ /**
3
+ * `PACKAGE.md` and `design-system/DESIGN.md` — the two regenerable projections.
4
+ *
5
+ * Neither is normative and neither is ever sealed: a baseline that selected one
6
+ * would make a published revision depend on something derived, so re-rendering
7
+ * the landing page would rewrite history. They exist because a human opening a
8
+ * dossier needs a way in, and because Stitch-style handoff reads `DESIGN.md`.
9
+ *
10
+ * The rule that keeps them honest: a projection **repeats no normative
11
+ * content**. It points at where things live and says which revision it was
12
+ * rendered from. Anything a projection asserted on its own would be a second
13
+ * source of truth for a fact the manifest or the artifact already owns.
14
+ */
15
+ /** Marker line that ties a rendered projection to the revision it came from. */
16
+ const SOURCE_MARK = "<!-- workline:projection source=";
17
+ export function sourceMark(packageId, revision) {
18
+ // `@r0` no existe: una proyección de un package sin publicar declara eso y no
19
+ // una revisión que nadie puede resolver.
20
+ return `${SOURCE_MARK}${sourceSuffix(packageId, revision)} -->`;
21
+ }
22
+ /** How a source revision is written inside a projection mark. */
23
+ function sourceSuffix(packageId, revision) {
24
+ return revision === 0 ? `${packageId}@sin-publicar` : `${packageId}@r${revision}`;
25
+ }
26
+ /** The revision a projection declares it was rendered from, or null. */
27
+ export function declaredSource(text) {
28
+ const match = new RegExp(`${SOURCE_MARK}(\\S+) -->`).exec(text);
29
+ return match === null ? null : match[1];
30
+ }
31
+ /**
32
+ * The human landing page. Locations and identities only: a reader finds a flow,
33
+ * a screen, its states and its renditions, and then opens the artifact — which
34
+ * is where the design actually lives.
35
+ */
36
+ export function renderPackageMd(manifest) {
37
+ const current = manifest.current_baseline;
38
+ const lines = [
39
+ `# ${manifest.title}`,
40
+ "",
41
+ sourceMark(manifest.id, current?.revision ?? 0),
42
+ "",
43
+ "> Página regenerable. No es normativa y no forma parte de ningún digest:",
44
+ "> el manifest y los baselines son la autoridad.",
45
+ "",
46
+ `- **Identidad:** \`${manifest.id}\``,
47
+ `- **Baseline vigente:** ${current === null ? "sin publicar" : `\`${manifest.id}@r${current.revision}\``}`,
48
+ `- **Creado:** ${manifest.created}`,
49
+ ];
50
+ if (manifest.derived_from !== null) {
51
+ lines.push(`- **Derivado de:** \`${manifest.derived_from}\``);
52
+ }
53
+ for (const [heading, entries] of [
54
+ ["Flows", manifest.catalog.flows],
55
+ ["Screens", manifest.catalog.screens],
56
+ ["Reglas", manifest.catalog.rules],
57
+ ["Tokens", manifest.catalog.tokens],
58
+ ["Renditions", manifest.catalog.renditions],
59
+ ]) {
60
+ if (entries.length === 0)
61
+ continue;
62
+ lines.push("", `## ${heading}`, "");
63
+ for (const entry of currentRevisions(entries)) {
64
+ const maturity = entry.maturity === undefined ? "" : ` · ${entry.maturity}`;
65
+ lines.push(`- \`${entry.id}@r${entry.revision}\`${maturity} — [\`${entry.path}\`](${entry.path})`);
66
+ // Un estado se localiza por su referencia completa; lo que ese estado DICE
67
+ // sigue viviendo solo en el documento.
68
+ for (const anchor of entry.states ?? []) {
69
+ lines.push(` - \`${manifest.id}/${entry.id}@r${entry.revision}#${anchor}\` — [\`${entry.path}\`](${entry.path})`);
70
+ }
71
+ }
72
+ }
73
+ if (manifest.catalog.assets.length > 0) {
74
+ lines.push("", "## Assets", "", `${manifest.catalog.assets.length} content-addressed bajo \`assets/\`.`);
75
+ }
76
+ const consumers = [...manifest.relations.specs, ...manifest.relations.plans];
77
+ if (consumers.length > 0) {
78
+ lines.push("", "## Consumido por", "");
79
+ // Ruta relativa al workspace, no un enlace: el dossier puede vivir en una
80
+ // subcarpeta de `docs/designs/`, y un `../../../` fijo apuntaría a la nada.
81
+ for (const path of consumers)
82
+ lines.push(`- \`${path}\``);
83
+ }
84
+ return `${lines.join("\n")}\n`;
85
+ }
86
+ /**
87
+ * The agent-friendly ruleset. It lists the rules in force and where they live;
88
+ * it never restates what a rule SAYS, because the rule file owns that.
89
+ */
90
+ export function renderDesignMd(manifest) {
91
+ const current = manifest.current_baseline;
92
+ const rules = currentRevisions(manifest.catalog.rules);
93
+ const lines = [
94
+ `# Design rules — ${manifest.title}`,
95
+ "",
96
+ sourceMark(manifest.id, current?.revision ?? 0),
97
+ "",
98
+ "> Proyección regenerable del ruleset vigente, fuera del digest normativo.",
99
+ "> Cada regla es autoridad de su propio contenido: acá solo se listan.",
100
+ "",
101
+ ];
102
+ if (rules.length === 0) {
103
+ lines.push("Este package no declara reglas de design system.");
104
+ }
105
+ else {
106
+ for (const rule of rules) {
107
+ lines.push(`- \`${rule.id}@r${rule.revision}\` — [\`${rule.path}\`](../${rule.path})`);
108
+ }
109
+ }
110
+ const tokens = currentRevisions(manifest.catalog.tokens);
111
+ if (tokens.length > 0) {
112
+ lines.push("", "## Tokens", "");
113
+ for (const token of tokens) {
114
+ lines.push(`- \`${token.id}@r${token.revision}\` — [\`${token.path}\`](../${token.path})`);
115
+ }
116
+ }
117
+ return `${lines.join("\n")}\n`;
118
+ }
119
+ /**
120
+ * A projection is checkable against the manifest: regenerate it and compare.
121
+ * A drifted one is reported rather than trusted — it is the only thing a reader
122
+ * sees first, and a stale landing page sends them to a file that moved.
123
+ */
124
+ export function checkProjection(path, actual, manifest) {
125
+ if (!PROJECTIONS.includes(path)) {
126
+ return [
127
+ {
128
+ code: "DESIGN_FIELD_INVALID",
129
+ artifact: path,
130
+ message: `'${path}' no es una proyección del contrato`,
131
+ action: `las proyecciones son: ${PROJECTIONS.join(", ")}`,
132
+ },
133
+ ];
134
+ }
135
+ const expected = path === "PACKAGE.md" ? renderPackageMd(manifest) : renderDesignMd(manifest);
136
+ // Un checkout con `core.autocrlf` deja CRLF en disco. Comparar fines de línea
137
+ // reportaría stale una proyección correcta, y culpando a la revisión.
138
+ if (actual.replace(/\r\n/g, "\n") === expected)
139
+ return [];
140
+ const declared = declaredSource(actual);
141
+ const current = manifest.current_baseline;
142
+ const now = sourceSuffix(manifest.id, current?.revision ?? 0);
143
+ return [
144
+ {
145
+ code: "DESIGN_PROJECTION_STALE",
146
+ artifact: path,
147
+ message: declared === now
148
+ ? `'${path}' dice venir de ${now} y no coincide con lo que el manifest describe`
149
+ : `'${path}' fue renderizada desde ${declared ?? "una revisión que no declara"} y la vigente es ${now}`,
150
+ action: "regeneralá desde el manifest: es una proyección, no una fuente",
151
+ },
152
+ ];
153
+ }
154
+ /** Highest revision per id — what the package IS right now. */
155
+ function currentRevisions(entries) {
156
+ const byId = new Map();
157
+ for (const entry of entries) {
158
+ const seen = byId.get(entry.id);
159
+ if (seen === undefined || entry.revision > seen.revision)
160
+ byId.set(entry.id, entry);
161
+ }
162
+ return [...byId.values()].sort((a, b) => (a.id < b.id ? -1 : 1));
163
+ }
164
+ export { currentRevisions };
165
+ //# sourceMappingURL=projections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projections.js","sourceRoot":"","sources":["../../../src/domain/design/projections.ts"],"names":[],"mappings":"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"}