@tacuchi/agent-workflow-cli 20.25.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 (124) 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/self/install-skill.js +25 -8
  17. package/dist/application/self/install-skill.js.map +1 -1
  18. package/dist/application/semantic-operation/protocol.js +18 -12
  19. package/dist/application/semantic-operation/protocol.js.map +1 -1
  20. package/dist/application/semantic-operation/publish.js +56 -9
  21. package/dist/application/semantic-operation/publish.js.map +1 -1
  22. package/dist/application/skills-resolver-service.js +19 -4
  23. package/dist/application/skills-resolver-service.js.map +1 -1
  24. package/dist/application/status-service.js +1 -0
  25. package/dist/application/status-service.js.map +1 -1
  26. package/dist/application/workline-index-service.js +6 -0
  27. package/dist/application/workline-index-service.js.map +1 -1
  28. package/dist/application/workspace-init-service.js +9 -1
  29. package/dist/application/workspace-init-service.js.map +1 -1
  30. package/dist/cli/commands/designs.js +110 -0
  31. package/dist/cli/commands/designs.js.map +1 -0
  32. package/dist/cli/commands/index.js +2 -0
  33. package/dist/cli/commands/index.js.map +1 -1
  34. package/dist/cli/commands/resume.js +8 -0
  35. package/dist/cli/commands/resume.js.map +1 -1
  36. package/dist/cli/commands/status.js +45 -0
  37. package/dist/cli/commands/status.js.map +1 -1
  38. package/dist/cli/help-groups.js +3 -0
  39. package/dist/cli/help-groups.js.map +1 -1
  40. package/dist/cli/parser.js +1 -0
  41. package/dist/cli/parser.js.map +1 -1
  42. package/dist/domain/design/artifact-body.js +223 -0
  43. package/dist/domain/design/artifact-body.js.map +1 -0
  44. package/dist/domain/design/artifact.js +606 -0
  45. package/dist/domain/design/artifact.js.map +1 -0
  46. package/dist/domain/design/baseline.js +359 -0
  47. package/dist/domain/design/baseline.js.map +1 -0
  48. package/dist/domain/design/capability.js +51 -0
  49. package/dist/domain/design/capability.js.map +1 -0
  50. package/dist/domain/design/closure.js +161 -0
  51. package/dist/domain/design/closure.js.map +1 -0
  52. package/dist/domain/design/governance.js +298 -0
  53. package/dist/domain/design/governance.js.map +1 -0
  54. package/dist/domain/design/identity.js +145 -0
  55. package/dist/domain/design/identity.js.map +1 -0
  56. package/dist/domain/design/manifest.js +552 -0
  57. package/dist/domain/design/manifest.js.map +1 -0
  58. package/dist/domain/design/maturity.js +234 -0
  59. package/dist/domain/design/maturity.js.map +1 -0
  60. package/dist/domain/design/naming.js +117 -0
  61. package/dist/domain/design/naming.js.map +1 -0
  62. package/dist/domain/design/projections.js +165 -0
  63. package/dist/domain/design/projections.js.map +1 -0
  64. package/dist/domain/design/reference.js +234 -0
  65. package/dist/domain/design/reference.js.map +1 -0
  66. package/dist/domain/design/retired.js +61 -0
  67. package/dist/domain/design/retired.js.map +1 -0
  68. package/dist/domain/design/revision.js +219 -0
  69. package/dist/domain/design/revision.js.map +1 -0
  70. package/dist/domain/design/secrets.js +86 -0
  71. package/dist/domain/design/secrets.js.map +1 -0
  72. package/dist/domain/design/validation.js +75 -0
  73. package/dist/domain/design/validation.js.map +1 -0
  74. package/dist/domain/design/yaml-subset.js +390 -0
  75. package/dist/domain/design/yaml-subset.js.map +1 -0
  76. package/dist/domain/safe-path.js +23 -0
  77. package/dist/domain/safe-path.js.map +1 -0
  78. package/dist/domain/skills.js +27 -3
  79. package/dist/domain/skills.js.map +1 -1
  80. package/package.json +1 -1
  81. package/skills/w/SKILL.md +13 -11
  82. package/skills/w/artifacts/README.md +3 -4
  83. package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +2 -2
  84. package/skills/w/commands/README.md +2 -0
  85. package/skills/w/commands/export-diagrams.md +1 -1
  86. package/skills/w/commands/export-manuals.md +1 -1
  87. package/skills/w/commands/export-reports.md +1 -1
  88. package/skills/w/commands/export-scripts.md +1 -1
  89. package/skills/w/commands/fix-git.md +1 -1
  90. package/skills/w/commands/generate-launch.md +2 -2
  91. package/skills/w/commands/persist.md +2 -2
  92. package/skills/w/commands/plan-exec.md +13 -7
  93. package/skills/w/commands/plan-new.md +8 -4
  94. package/skills/w/commands/plan-refine.md +8 -5
  95. package/skills/w/commands/quick.md +4 -4
  96. package/skills/w/commands/resume.md +2 -2
  97. package/skills/w/commands/spec-new.md +4 -4
  98. package/skills/w/commands/spec-refine.md +3 -2
  99. package/skills/w/commands/status.md +1 -1
  100. package/skills/w/commands/workspace-init.md +1 -1
  101. package/skills/w/context/MANIFEST.json +19 -8
  102. package/skills/w/harness/HARNESS.md +14 -10
  103. package/skills/w/loops/CHASSIS.md +9 -8
  104. package/skills/w/loops/CODE-POLICIES.md +22 -7
  105. package/skills/w/loops/README.md +1 -1
  106. package/skills/w/loops/plan-exec-loop/LOOP.md +127 -61
  107. package/skills/w/loops/plan-new-loop/LOOP.md +66 -70
  108. package/skills/w/loops/plan-refine-loop/LOOP.md +15 -7
  109. package/skills/w/loops/spec-refine-loop/LOOP.md +14 -12
  110. package/skills/w/modules/DESIGN-REFERENCES.md +109 -0
  111. package/skills/w/modules/PERSIST-ROUTING.md +1 -0
  112. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +84 -0
  113. package/skills/w/roles/README.md +7 -5
  114. package/skills/w/roles/design/ROLE.md +217 -0
  115. package/skills/w/schemas/design/design-baseline.v1.schema.json +71 -0
  116. package/skills/w/schemas/design/design-manifest.v1.schema.json +322 -0
  117. package/skills/w/schemas/design/design-review.v1.schema.json +72 -0
  118. package/skills/w/schemas/design/design-revocation.v1.schema.json +54 -0
  119. package/skills/w/schemas/design/ui-flow.v1.schema.json +211 -0
  120. package/skills/w/schemas/design/ui-screen.v1.schema.json +214 -0
  121. package/skills/w/artifacts/artifacts-design/SPEC.md +0 -42
  122. package/skills/w/modules/PLAN-DESIGN-SPECS.md +0 -12
  123. package/skills/w/modules/PLAN-REFINE-DESIGN-SPECS.md +0 -7
  124. package/skills/w/roles/ui-spec/ROLE.md +0 -147
@@ -0,0 +1,298 @@
1
+ import { createHash } from "node:crypto";
2
+ import { canonicalJson } from "../../application/semantic-operation/protocol.js";
3
+ import { isCalendarDate } from "./baseline.js";
4
+ import { CANONICAL_SCHEMAS } from "./capability.js";
5
+ import { isDigest, parseBaselineRef } from "./identity.js";
6
+ import { Reader, isNonEmptyString, isRecord, } from "./validation.js";
7
+ export const REVIEW_ALLOWED_KEYS = {
8
+ "": [
9
+ "schema",
10
+ "id",
11
+ "target",
12
+ "target_digest",
13
+ "author",
14
+ "date",
15
+ "decision",
16
+ "evidence",
17
+ "digest",
18
+ ],
19
+ };
20
+ export const REVOCATION_ALLOWED_KEYS = {
21
+ "": ["schema", "id", "target", "target_digest", "author", "date", "reason", "digest"],
22
+ };
23
+ const DECISIONS = new Set(["proposed", "approved", "rejected"]);
24
+ /**
25
+ * A record's own digest, over its canonical JSON WITHOUT `digest`.
26
+ *
27
+ * The same rule a baseline uses. Including the field would make the record
28
+ * unverifiable — you cannot hash a value that contains its own hash.
29
+ */
30
+ export function computeRecordDigest(record) {
31
+ const { digest: _drop, ...rest } = record;
32
+ return `sha256:${createHash("sha256").update(canonicalJson(rest), "utf8").digest("hex")}`;
33
+ }
34
+ export function validateDesignReview(raw, artifact) {
35
+ const r = new Reader(REVIEW_ALLOWED_KEYS);
36
+ const common = readCommon(r, raw, artifact, "REV", CANONICAL_SCHEMAS.review);
37
+ if (common === null)
38
+ return { ok: false, value: null, failures: r.failures, touched: r.touched };
39
+ const decision = r.read(common.node, "decision");
40
+ const evidence = r.read(common.node, "evidence");
41
+ if (typeof decision !== "string" || !DECISIONS.has(decision)) {
42
+ r.invalid(artifact, "'decision' debe ser 'proposed', 'approved' o 'rejected'", "una revisión nace 'proposed'; solo 'approved' concede algo");
43
+ }
44
+ if (!Array.isArray(evidence) || !evidence.every(isNonEmptyString)) {
45
+ r.invalid(artifact, "'evidence' debe ser una lista de strings", "usá [] si la decisión no cita nada: la evidencia nunca reemplaza a la decisión");
46
+ }
47
+ else if (new Set(evidence).size !== evidence.length) {
48
+ r.fail("DESIGN_ID_DUPLICATE", artifact, "'evidence' repite una entrada", "citar dos veces la misma fuente no la hace más evidencia");
49
+ }
50
+ if (r.failures.length > 0)
51
+ return { ok: false, value: null, failures: r.failures, touched: r.touched };
52
+ const value = {
53
+ ...common.value,
54
+ schema: CANONICAL_SCHEMAS.review,
55
+ decision: decision,
56
+ evidence: evidence,
57
+ };
58
+ return finish(r, value, artifact);
59
+ }
60
+ export function validateDesignRevocation(raw, artifact) {
61
+ const r = new Reader(REVOCATION_ALLOWED_KEYS);
62
+ const common = readCommon(r, raw, artifact, "RVK", CANONICAL_SCHEMAS.revocation);
63
+ if (common === null)
64
+ return { ok: false, value: null, failures: r.failures, touched: r.touched };
65
+ const reason = r.read(common.node, "reason");
66
+ if (!isNonEmptyString(reason)) {
67
+ r.invalid(artifact, "'reason' es obligatorio y no puede estar vacío", "un bloqueo sin razón no es auditable");
68
+ return { ok: false, value: null, failures: r.failures, touched: r.touched };
69
+ }
70
+ const value = {
71
+ ...common.value,
72
+ schema: CANONICAL_SCHEMAS.revocation,
73
+ reason,
74
+ };
75
+ return finish(r, value, artifact);
76
+ }
77
+ function readCommon(r, raw, artifact, prefix, schema) {
78
+ if (!isRecord(raw)) {
79
+ r.fail("DESIGN_RECORD_NOT_OBJECT", artifact, "el record de gobierno no es un objeto JSON", "un record es un documento JSON con su propio digest");
80
+ return null;
81
+ }
82
+ // El gate de versión corre PRIMERO y solo, como en los tres módulos hermanos:
83
+ // leer campos de un formato que no conocemos reporta un montón de sinsentidos
84
+ // derivados, y manda a arreglar un campo cuando lo que falta es actualizar.
85
+ const declared = r.read(raw, "schema");
86
+ if (declared !== schema) {
87
+ r.fail("DESIGN_SCHEMA_UNKNOWN", artifact, `versión de formato no soportada: ${JSON.stringify(declared)}`, `este Workline entiende ${schema}`);
88
+ return null;
89
+ }
90
+ r.closed(raw, "", artifact);
91
+ const id = r.read(raw, "id");
92
+ const target = r.read(raw, "target");
93
+ const targetDigest = r.read(raw, "target_digest");
94
+ const author = r.read(raw, "author");
95
+ const date = r.read(raw, "date");
96
+ const digest = r.read(raw, "digest");
97
+ if (typeof id !== "string" || !new RegExp(`^${prefix}-(?:[0-9]{3}|[1-9][0-9]{3,})$`).test(id)) {
98
+ r.invalid(artifact, `'id' debe ser ${prefix}-NNN`, `numerá el record como ${prefix}-001`);
99
+ }
100
+ if (parseBaselineRef(target) === null) {
101
+ r.invalid(artifact, "'target' debe ser el baseline exacto DES-NNN@rN", "un record decide sobre UNA revisión, no sobre un package");
102
+ }
103
+ if (!isDigest(targetDigest)) {
104
+ r.invalid(artifact, "'target_digest' debe ser el sha256 que ese baseline tenía", "sin el digest el record aprueba un nombre, no unos bytes");
105
+ }
106
+ if (!isNonEmptyString(author)) {
107
+ r.invalid(artifact, "'author' es obligatorio", "nombrá a quien decidió, o el rol que lo hizo");
108
+ }
109
+ // Que EXISTA, no solo que tenga la forma: `decisionOn` ordena por esta fecha,
110
+ // así que un 9999-99-99 se ancla arriba y ninguna decisión real lo desplaza.
111
+ if (typeof date !== "string" || !isCalendarDate(date)) {
112
+ r.invalid(artifact, "'date' debe ser un día real AAAA-MM-DD", "fechá la decisión");
113
+ }
114
+ if (!isDigest(digest)) {
115
+ r.invalid(artifact, "'digest' debe ser un sha256", "sellá el record con su propio digest");
116
+ }
117
+ if (r.failures.length > 0)
118
+ return null;
119
+ return {
120
+ node: raw,
121
+ value: {
122
+ id: id,
123
+ target: target,
124
+ target_digest: targetDigest,
125
+ author: author,
126
+ date: date,
127
+ digest: digest,
128
+ },
129
+ };
130
+ }
131
+ /** The record's own seal has to match what the record says. */
132
+ function finish(r, value, artifact) {
133
+ const expected = computeRecordDigest(value);
134
+ if (expected !== value.digest) {
135
+ r.fail("DESIGN_DIGEST_MISMATCH", artifact, `'digest' dice ${value.digest} y el contenido sella ${expected}`, "recalculá el digest sobre el JSON canónico sin el campo 'digest'");
136
+ return { ok: false, value: null, failures: r.failures, touched: r.touched };
137
+ }
138
+ return { ok: true, value, failures: [], touched: r.touched };
139
+ }
140
+ export function judgeExecution(manifest, baselineRef, records, policy) {
141
+ const parsed = parseBaselineRef(baselineRef);
142
+ const notices = [];
143
+ const failures = [];
144
+ if (parsed === null || parsed.package !== manifest.id) {
145
+ return {
146
+ executable: false,
147
+ notices,
148
+ failures: [
149
+ {
150
+ code: "DESIGN_REFERENCE_MISSING",
151
+ artifact: baselineRef,
152
+ message: `'${baselineRef}' no es un baseline de ${manifest.id}`,
153
+ action: "referenciá el baseline exacto DES-NNN@rN del package",
154
+ },
155
+ ],
156
+ };
157
+ }
158
+ const published = manifest.baselines.find((b) => b.revision === parsed.revision);
159
+ if (published === undefined) {
160
+ return {
161
+ executable: false,
162
+ notices,
163
+ failures: [
164
+ {
165
+ code: "DESIGN_REFERENCE_MISSING",
166
+ artifact: baselineRef,
167
+ message: `${manifest.id} no publicó la revisión r${parsed.revision}`,
168
+ action: `revisiones publicadas: ${manifest.baselines.map((b) => `r${b.revision}`).join(", ")}`,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ const revocation = records.find((record) => isRevocation(record) && decidesOn(record, baselineRef, published.digest));
174
+ if (revocation !== undefined) {
175
+ failures.push({
176
+ code: "DESIGN_REVISION_REVOKED",
177
+ artifact: baselineRef,
178
+ message: `${baselineRef} está revocada: ${revocation.reason}`,
179
+ action: "una revocación explícita es la única prohibición: usá otra revisión",
180
+ });
181
+ return { executable: false, notices, failures };
182
+ }
183
+ // Superseded AVISA y sigue ejecutable: publicar la siguiente no invalida una
184
+ // referencia que alguien fijó a propósito.
185
+ const current = manifest.current_baseline;
186
+ if (current !== null && current.revision > parsed.revision) {
187
+ notices.push(`${baselineRef} está superseded por ${manifest.id}@r${current.revision}; sigue ejecutable`);
188
+ }
189
+ if (policy.requireApproval) {
190
+ failures.push(...requireApproved(baselineRef, published.digest, records));
191
+ }
192
+ return { executable: failures.length === 0, notices, failures };
193
+ }
194
+ /**
195
+ * AC-SEM-10: an approval covers ONE baseline and never the next.
196
+ *
197
+ * A new revision is born `proposed` by construction — there simply is no record
198
+ * naming it — so nothing has to reset anything. Inheritance is impossible rather
199
+ * than forbidden, which is the stronger of the two.
200
+ */
201
+ function requireApproved(baselineRef, digest, records) {
202
+ // La decisión VIGENTE, no «¿alguna vez hubo un approved?»: si review fuera un
203
+ // acumulador monótono, una aprobación sería irretirable y el único remedio
204
+ // pasaría a ser una revocación, que es otra dimensión y otra causa.
205
+ if (decisionOn(baselineRef, records, digest) === "approved")
206
+ return [];
207
+ return [
208
+ {
209
+ code: "DESIGN_APPROVAL_MISSING",
210
+ artifact: baselineRef,
211
+ message: `la política exige aprobación y ${baselineRef} no tiene un review 'approved'`,
212
+ action: "aprobá esa revisión exacta: una aprobación no se hereda de la anterior",
213
+ },
214
+ ];
215
+ }
216
+ /**
217
+ * Whether a record decides on THIS revision — by name and by BYTES.
218
+ *
219
+ * `target_digest` is what makes the record about a thing instead of about a
220
+ * number: a revision republished with the same number and different content is
221
+ * not the revision anybody approved.
222
+ */
223
+ function decidesOn(record, baselineRef, digest) {
224
+ return record.target === baselineRef && record.target_digest === digest;
225
+ }
226
+ /**
227
+ * The index and the records have to say the same thing (mirrors `checkBaselineAuthority`).
228
+ *
229
+ * `governance.reviews[]` declares an id, a path, a digest and a target; the file
230
+ * at that path declares its own. Nobody was comparing them, so a manifest could
231
+ * index `REV-001 @r2 sha256:3333…` while the file said `REV-777 @r1 sha256:0a60…`
232
+ * and both halves validated on their own. An index that can disagree with what
233
+ * it indexes is a second, silent source of truth.
234
+ */
235
+ export function checkGovernanceAuthority(manifest, records, packagePath) {
236
+ const failures = [];
237
+ const indexed = [
238
+ ...manifest.governance.reviews.map((e) => ({ ...e, kind: "review" })),
239
+ ...manifest.governance.revocations.map((e) => ({ ...e, kind: "revocation" })),
240
+ ];
241
+ for (const entry of indexed) {
242
+ const artifact = `${packagePath}/${entry.path}`;
243
+ const record = records.get(entry.path);
244
+ if (record === undefined) {
245
+ failures.push({
246
+ code: "DESIGN_REFERENCE_FILE_MISSING",
247
+ artifact,
248
+ message: `el manifest indexa ${entry.id} y '${entry.path}' no está`,
249
+ action: "restauralo, o sacá la entrada del índice",
250
+ });
251
+ continue;
252
+ }
253
+ for (const [what, indexedValue, realValue] of [
254
+ ["id", entry.id, record.id],
255
+ ["target", entry.target, record.target],
256
+ ["digest", entry.digest, record.digest],
257
+ ]) {
258
+ if (indexedValue === realValue)
259
+ continue;
260
+ failures.push({
261
+ code: "DESIGN_AUTHORITY_CONFLICT",
262
+ artifact,
263
+ message: `el índice dice ${what} ${indexedValue} y el record dice ${realValue}`,
264
+ action: "el record es la autoridad: corregí el índice del manifest",
265
+ });
266
+ }
267
+ const isRev = isReview(record);
268
+ if ((entry.kind === "review") !== isRev) {
269
+ failures.push({
270
+ code: "DESIGN_AUTHORITY_CONFLICT",
271
+ artifact,
272
+ message: `${entry.id} está indexado como ${entry.kind} y el record es otra cosa`,
273
+ action: "una aprobación y una revocación no son intercambiables",
274
+ });
275
+ }
276
+ }
277
+ return failures;
278
+ }
279
+ export function isReview(record) {
280
+ return record.schema === CANONICAL_SCHEMAS.review;
281
+ }
282
+ export function isRevocation(record) {
283
+ return record.schema === CANONICAL_SCHEMAS.revocation;
284
+ }
285
+ /**
286
+ * The decision standing on a baseline right now.
287
+ *
288
+ * The LAST record by date wins, and a baseline nobody reviewed is `proposed` —
289
+ * the state everything is born in.
290
+ */
291
+ export function decisionOn(baselineRef, records, digest) {
292
+ const reviews = records
293
+ .filter(isReview)
294
+ .filter((review) => digest === undefined ? review.target === baselineRef : decidesOn(review, baselineRef, digest))
295
+ .sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : a.id < b.id ? -1 : 1));
296
+ return reviews.at(-1)?.decision ?? "proposed";
297
+ }
298
+ //# sourceMappingURL=governance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.js","sourceRoot":"","sources":["../../../src/domain/design/governance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Identity of a UI Design Package and of the artifacts inside it.
3
+ *
4
+ * The rule the whole contract rests on: an identifier derives from NOTHING — not
5
+ * a spec, a plan, a session, the folder slug, the path or a provider. It is
6
+ * minted once, stored in the manifest, and survives every rename or move. The
7
+ * `NNN-design-<slug>` folder prefix is a human affordance for browsing; nothing
8
+ * resolves through it.
9
+ *
10
+ * This module owns the reference GRAMMAR (what a well-formed identifier looks
11
+ * like). Resolving a reference against the workspace — repairing a stale path
12
+ * hint, rejecting an approximate match, walking a revision line — belongs to the
13
+ * resolver built on top of it.
14
+ */
15
+ /**
16
+ * THE grammar, as pattern fragments.
17
+ *
18
+ * Every regex in this module and every `pattern` in the three published JSON
19
+ * Schemas is built from these strings — and a guard test proves the schemas use
20
+ * them. Without that, tightening a regex here silently leaves the normative
21
+ * contract describing something looser, which is exactly what happened once.
22
+ *
23
+ * `DES-0001` and `DES-001` must never be two spellings of one identity, and
24
+ * `@r04` must never be another spelling of `@r4`: references are compared as
25
+ * STRINGS everywhere downstream, so two spellings break every comparison.
26
+ */
27
+ export const GRAMMAR = {
28
+ packageId: "DES-(?:[0-9]{3}|[1-9][0-9]{3,})",
29
+ /** Suffix after a kind prefix, e.g. `FLW` + this. */
30
+ serial: "-(?:[0-9]{3}|[1-9][0-9]{3,})",
31
+ revision: "[1-9][0-9]{0,5}",
32
+ anchor: "[A-Za-z0-9][A-Za-z0-9_-]*",
33
+ digest: "sha256:[0-9a-f]{64}",
34
+ };
35
+ /** `FLW|SCR` → `(?:FLW|SCR)-(?:[0-9]{3}|[1-9][0-9]{3,})`. */
36
+ export function artifactIdPattern(prefixes) {
37
+ return `(?:${prefixes})${GRAMMAR.serial}`;
38
+ }
39
+ const ALL_PREFIXES = "FLW|SCR|RUL|TOK|VIS|REV|RVK";
40
+ const PACKAGE_ID_RE = new RegExp(`^${GRAMMAR.packageId}$`);
41
+ /** ID prefix per artifact kind. Assets have none: they are content-addressed. */
42
+ export const ARTIFACT_PREFIX = {
43
+ flow: "FLW",
44
+ screen: "SCR",
45
+ rule: "RUL",
46
+ token: "TOK",
47
+ rendition: "VIS",
48
+ review: "REV",
49
+ revocation: "RVK",
50
+ };
51
+ const ARTIFACT_ID_RE = new RegExp(`^${artifactIdPattern(ALL_PREFIXES)}$`);
52
+ /** `sha256:` + 64 lowercase hex chars. The only digest form the package writes. */
53
+ const DIGEST_RE = new RegExp(`^${GRAMMAR.digest}$`);
54
+ /** `<sha256>-<safe-name>.<ext>` — the content-addressed asset file name. */
55
+ const ASSET_FILENAME_RE = /^[0-9a-f]{64}-[A-Za-z0-9._-]+$/;
56
+ export function isPackageId(value) {
57
+ return typeof value === "string" && PACKAGE_ID_RE.test(value);
58
+ }
59
+ export function isArtifactId(value, kind) {
60
+ if (typeof value !== "string" || !ARTIFACT_ID_RE.test(value))
61
+ return false;
62
+ return kind === undefined || value.startsWith(`${ARTIFACT_PREFIX[kind]}-`);
63
+ }
64
+ export function isDigest(value) {
65
+ return typeof value === "string" && DIGEST_RE.test(value);
66
+ }
67
+ export function isAssetFilename(value) {
68
+ return ASSET_FILENAME_RE.test(value);
69
+ }
70
+ const BASELINE_REF_RE = new RegExp(`^(${GRAMMAR.packageId})@r(${GRAMMAR.revision})$`);
71
+ const ARTIFACT_REF_RE = new RegExp(`^(${GRAMMAR.packageId})/(${artifactIdPattern(ALL_PREFIXES)})@r(${GRAMMAR.revision})(?:#(${GRAMMAR.anchor}))?$`);
72
+ export function parseBaselineRef(raw) {
73
+ if (typeof raw !== "string")
74
+ return null;
75
+ const m = BASELINE_REF_RE.exec(raw);
76
+ if (m === null)
77
+ return null;
78
+ const revision = Number(m[2]);
79
+ if (!isRevision(revision))
80
+ return null;
81
+ return { package: m[1], revision };
82
+ }
83
+ const ARTIFACT_ID_QUALIFIED_RE = new RegExp(`^(${GRAMMAR.packageId})/(${artifactIdPattern(ALL_PREFIXES)})$`);
84
+ export function parseArtifactId(raw) {
85
+ if (typeof raw !== "string")
86
+ return null;
87
+ const m = ARTIFACT_ID_QUALIFIED_RE.exec(raw);
88
+ if (m === null)
89
+ return null;
90
+ return { package: m[1], artifact: m[2] };
91
+ }
92
+ /**
93
+ * The same grammar with the `g` flag, for scanning prose. Cross-validation only
94
+ * ever recognizes this exact form — never an informally written mention.
95
+ */
96
+ export const ARTIFACT_REF_GLOBAL = new RegExp(`${GRAMMAR.packageId}/${artifactIdPattern(ALL_PREFIXES)}@r${GRAMMAR.revision}(?:#${GRAMMAR.anchor})?`, "g");
97
+ /**
98
+ * An acceptance criterion as Workline writes it: `S013/AC-SEM-11`, `S046/AC-01`.
99
+ * Cross-validation harvests these from the body the same way it harvests
100
+ * references — closed grammar only, never a sentence.
101
+ */
102
+ export const CRITERION_GLOBAL = /S\d{3}\/AC-(?:[A-Z]+-)?\d+/g;
103
+ export function parseArtifactRef(raw) {
104
+ if (typeof raw !== "string")
105
+ return null;
106
+ const m = ARTIFACT_REF_RE.exec(raw);
107
+ if (m === null)
108
+ return null;
109
+ const revision = Number(m[3]);
110
+ if (!isRevision(revision))
111
+ return null;
112
+ const artifact = m[2];
113
+ // Only a screen has states. An anchor on a flow, rule, token or rendition is
114
+ // not a stricter reference — it is a reference to something that cannot exist,
115
+ // and letting it parse means the diagnostic later blames the wrong thing.
116
+ if (m[4] !== undefined && !artifact.startsWith("SCR-"))
117
+ return null;
118
+ return {
119
+ package: m[1],
120
+ artifact,
121
+ revision,
122
+ ...(m[4] !== undefined ? { state: m[4] } : {}),
123
+ };
124
+ }
125
+ /**
126
+ * No `trim()` on the parsers above, on purpose: `"DES-001@r1 "` would be a
127
+ * second spelling of one identity, and every comparison downstream is by
128
+ * string. Whoever reads from Markdown trims before parsing.
129
+ */
130
+ /** Revisions are logical and start at 1: `@r0` is not a thing. */
131
+ export function isRevision(value) {
132
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1;
133
+ }
134
+ /**
135
+ * True when a reference would parse if it dropped its state anchor — i.e. the
136
+ * anchor is the only thing wrong with it. Lets a call site keep the precise
137
+ * diagnostic ("this list references whole revisions") without restating the
138
+ * rule that only screens have states.
139
+ */
140
+ export function anchorIsTheProblem(raw) {
141
+ if (typeof raw !== "string" || !raw.includes("#"))
142
+ return false;
143
+ return parseArtifactRef(raw) === null && parseArtifactRef(raw.split("#")[0]) !== null;
144
+ }
145
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/domain/design/identity.ts"],"names":[],"mappings":"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"}