@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
package/README.md CHANGED
@@ -24,7 +24,7 @@ Workline has three layers plus a permanent `docs/` zone:
24
24
  - **Layer 2 · Loops** — the AI runs them whole: `spec-refine-loop` · `plan-new-loop` · `plan-refine-loop` · `plan-exec-loop` · `quick-loop` — all heirs of the shared engine `skills/w/loops/CHASSIS.md` (+ `CODE-POLICIES.md` for the code-editing loops). Each loop is a **persistent goal** that runs until its success criteria are green (verification-first); gap-driven, with **structured-choice** lifecycle control (compact/close — `AskUserQuestion` on Claude Code, numbered markdown elsewhere) and resumable `CHECKPOINT`.
25
25
  - **Layer 3 · Sessions + artifacts** — internal, ephemeral process state under `.workflow/sessions/` (`SESSION` · `CHECKPOINT` · `BACKLOG` · `SCRIPTS.sql` · `ANALYSIS-FILE` · `CONCLUSIONS` · `DECISION` · …). Sessions are slug-named folders, created by loops, never by the user.
26
26
 
27
- **Pluggable capabilities.** Loops compose capability **roles** (`ui-design`, `sql`, `git`, `research`, `diagrams`, `overview`); the concrete skill bound to each role is resolved via `.workflow/skills.toml` (cascade: built-in default → `~/.workflow/skills.toml` → workspace). Inspect bindings with `aw skills` (advisory: it also warns when a bound skill is not installed in the standard skill roots — the binding itself is not auto-validated). Code/testing/writing conventions **and tool authoring** (`creating-tools`) are **not** roles — they're ambient skills the host auto-applies when present, independent of Workline. Per-source launch scripts live under `.workflow/launch/` (machine-specific, gitignored); created tools live under `docs/tools/`.
27
+ **Pluggable capabilities.** Loops compose capability **roles** (`design`, `sql`, `git`, `research`, `diagrams`, `overview`); the concrete skill bound to each role is resolved via `.workflow/skills.toml` (cascade: built-in default → `~/.workflow/skills.toml` → workspace). Inspect bindings with `aw skills` (advisory: it also warns when a bound skill is not installed in the standard skill roots — the binding itself is not auto-validated). Code/testing/writing conventions **and tool authoring** (`creating-tools`) are **not** roles — they're ambient skills the host auto-applies when present, independent of Workline. Per-source launch scripts live under `.workflow/launch/` (machine-specific, gitignored); created tools live under `docs/tools/`.
28
28
 
29
29
  **Invariants.** No auto-export (only `export-*` writes `docs/`); the spec and plan are documents, not artifacts; DB scripts-only (never executes DML/DDL); git-safe (verifies the per-source working branch before edits; proposes commits).
30
30
 
@@ -5,6 +5,9 @@ export class NodeFileSystem {
5
5
  async readText(path) {
6
6
  return readFile(path, "utf8");
7
7
  }
8
+ async readBytes(path) {
9
+ return new Uint8Array(await readFile(path));
10
+ }
8
11
  /**
9
12
  * Atomic write: stage to `<path>.<pid>.<n>.tmp` and rename onto `path`.
10
13
  * `rename` is atomic on POSIX/NTFS within the same filesystem, so a concurrent
@@ -1 +1 @@
1
- {"version":3,"file":"node-file-system.js","sourceRoot":"","sources":["../../src/adapters/node-file-system.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node-file-system.js","sourceRoot":"","sources":["../../src/adapters/node-file-system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,246 @@
1
+ import { join } from "node:path";
2
+ import { validateDesignArtifact } from "../../domain/design/artifact.js";
3
+ import { computeClosure, notReadyForHandoff } from "../../domain/design/closure.js";
4
+ import { judgeExecution, validateDesignReview, validateDesignRevocation, } from "../../domain/design/governance.js";
5
+ import { parseSpecDesignReferences, parseTaskDesignReferences, } from "../../domain/design/reference.js";
6
+ import { reportRetiredDesign } from "../../domain/design/retired.js";
7
+ import { readDesignIndex } from "./design-index-service.js";
8
+ import { resolveBaselineOnDisk, resolveStateAnchor, resolveTaskReference, staleHintNotice, } from "./design-resolver-service.js";
9
+ /**
10
+ * Off by default (T7.3): `plan-exec` does not demand approval unless the
11
+ * workspace asks for it, and turning it on never promotes or alters a maturity.
12
+ */
13
+ export async function gatePlanDesign(fs, workspace, planPath, policy = { requireApproval: false }) {
14
+ const empty = { plan: planPath, declared: [], verdicts: [] };
15
+ const absolute = join(workspace, planPath);
16
+ if (!(await fs.exists(absolute))) {
17
+ return {
18
+ ...empty,
19
+ blocked: true,
20
+ failures: [
21
+ {
22
+ code: "DESIGN_GATE_PLAN_MISSING",
23
+ artifact: planPath,
24
+ message: `no existe '${planPath}'`,
25
+ action: "pasá la ruta del plan relativa al workspace",
26
+ },
27
+ ],
28
+ };
29
+ }
30
+ const text = await fs.readText(absolute);
31
+ const declared = parseSpecDesignReferences(text, planPath);
32
+ // ONE parse over the whole document, not one per line: the rule that a bare
33
+ // `DES-001` is only prose when the same text pins it needs the whole text to
34
+ // decide, and per-line it would report every prose mention of a pinned package.
35
+ const pinned = parseTaskDesignReferences(text, planPath);
36
+ // Legacy material is REPORTED here, at the gate, because this is where a
37
+ // document is consumed as input and as a gate's evidence — the two things the
38
+ // retired path is no longer allowed to be.
39
+ const failures = [
40
+ ...reportRetiredDesign(text, planPath),
41
+ ...declared.failures,
42
+ ...pinned.failures,
43
+ ];
44
+ if (pinned.references.length === 0) {
45
+ // A plan with no design roots is the normal shape of a plan without UI. Its
46
+ // own declared block is still reported if it is malformed.
47
+ return { ...empty, declared: declared.references, blocked: failures.length > 0, failures };
48
+ }
49
+ const index = await readDesignIndex(fs, workspace);
50
+ const packages = new PackageCache(fs, workspace, index);
51
+ const verdicts = [];
52
+ for (const reference of pinned.references) {
53
+ verdicts.push(await judgeReference(reference, {
54
+ fs,
55
+ workspace,
56
+ index,
57
+ packages,
58
+ planPath,
59
+ policy,
60
+ declared: declared.references,
61
+ owner: ownerOf(text, reference.raw, planPath),
62
+ }));
63
+ }
64
+ return {
65
+ plan: planPath,
66
+ blocked: failures.length > 0 || verdicts.some((v) => !v.ready),
67
+ declared: declared.references,
68
+ verdicts,
69
+ failures,
70
+ };
71
+ }
72
+ /** The three questions, in the only order that makes their answers meaningful. */
73
+ async function judgeReference(reference, ctx) {
74
+ const base = {
75
+ owner: ctx.owner,
76
+ raw: reference.raw,
77
+ notices: [],
78
+ failures: [],
79
+ };
80
+ const blocked = (failure) => ({
81
+ ...base,
82
+ ready: false,
83
+ failures: [...base.failures, failure],
84
+ });
85
+ // 1. Does it still resolve to the same bytes?
86
+ // The owner qualifies the plan only when it IS a phase or a task: for a
87
+ // reference sitting in prose the label already is the plan, and naming it
88
+ // twice reads as two artifacts.
89
+ const artifact = ctx.owner.kind === "document" ? ctx.planPath : `${ctx.planPath} (${ctx.owner.label})`;
90
+ const resolved = resolveTaskReference(ctx.index, reference, ctx.declared, artifact);
91
+ if (!resolved.ok)
92
+ return blocked(resolved.failure);
93
+ const onDisk = await resolveBaselineOnDisk(ctx.fs, ctx.workspace, resolved.value, artifact);
94
+ if (!onDisk.ok)
95
+ return blocked(onDisk.failure);
96
+ const anchored = await resolveStateAnchor(ctx.fs, ctx.workspace, resolved.value, artifact);
97
+ if (!anchored.ok)
98
+ return blocked(anchored.failure);
99
+ const stale = staleHintNotice(resolved.value, artifact);
100
+ if (stale !== null)
101
+ base.notices.push(`${stale.message} → ${stale.action}`);
102
+ const loaded = await ctx.packages.load(reference.baseline.package);
103
+ if (loaded === null) {
104
+ return blocked({
105
+ code: "DESIGN_REFERENCE_PACKAGE_INVALID",
106
+ artifact,
107
+ message: `${reference.baseline.package} no tiene un manifest válido que resolver`,
108
+ action: "corré 'aw designs --detail' y reparalo antes de ejecutar",
109
+ });
110
+ }
111
+ // 2. May this exact revision be executed?
112
+ const baselineRef = `${reference.baseline.package}@r${reference.baseline.revision}`;
113
+ const verdict = judgeExecution(loaded.manifest, baselineRef, loaded.records, ctx.policy);
114
+ base.notices.push(...verdict.notices);
115
+ if (!verdict.executable) {
116
+ return { ...base, ready: false, failures: [...base.failures, ...verdict.failures] };
117
+ }
118
+ // 3. Is what the task consumes implementable?
119
+ const root = `${reference.artifact.package}/${reference.artifact.artifact}@r${reference.artifact.revision}`;
120
+ const closure = computeClosure(loaded.manifest, [root], loaded.read);
121
+ if (closure.failures.length > 0) {
122
+ return { ...base, ready: false, failures: [...base.failures, ...closure.failures] };
123
+ }
124
+ const pending = notReadyForHandoff(loaded.manifest, closure);
125
+ if (pending.length > 0) {
126
+ return blocked({
127
+ code: "DESIGN_HANDOFF_INCOMPLETE",
128
+ artifact,
129
+ message: `la clausura de ${root} alcanza ${pending.length} revisión(es) que no están en 'handoff': ${pending.map((p) => p.ref).join(", ")}`,
130
+ action: "promové esa clausura a 'handoff' desde PLAN REFINE: plan-exec no rediseña ni completa un diseño incompleto",
131
+ });
132
+ }
133
+ return { ...base, ready: true };
134
+ }
135
+ /**
136
+ * Who pinned the reference. Attribution is by SEARCH over the document instead
137
+ * of a second parse: the reference text is unique enough to locate, and a parser
138
+ * that also had to track phase and task structure would be two contracts in one.
139
+ *
140
+ * The parse dedupes by literal text, so two tasks pinning the SAME root produce
141
+ * one verdict, attributed to the first. Nothing escapes: `blocked` is plan-wide,
142
+ * and the report is per reference rather than per task.
143
+ */
144
+ function ownerOf(text, raw, planPath) {
145
+ const lines = text.split(/\r?\n/);
146
+ let phase = null;
147
+ for (const [i, line] of lines.entries()) {
148
+ const heading = /^###\s+(F\d+)\b/.exec(line);
149
+ if (heading !== null)
150
+ phase = heading[1];
151
+ if (!line.includes(raw))
152
+ continue;
153
+ const task = /^\s*-\s*\[[ xX]\]\s*(T[\d.]*\d)\b/.exec(line);
154
+ if (task !== null)
155
+ return { kind: "task", label: task[1], line: i + 1 };
156
+ if (phase !== null)
157
+ return { kind: "phase", label: phase, line: i + 1 };
158
+ return { kind: "document", label: planPath, line: i + 1 };
159
+ }
160
+ return { kind: "document", label: planPath, line: 0 };
161
+ }
162
+ /**
163
+ * A package is read once per run.
164
+ *
165
+ * The closure needs a SYNCHRONOUS reader (it walks a graph and cannot await mid
166
+ * traversal), so the catalog documents are pre-read into a map here. Reading
167
+ * them per reference instead would re-read the same thirteen screens for every
168
+ * task that touches the package.
169
+ */
170
+ class PackageCache {
171
+ fs;
172
+ workspace;
173
+ index;
174
+ loaded = new Map();
175
+ constructor(fs, workspace, index) {
176
+ this.fs = fs;
177
+ this.workspace = workspace;
178
+ this.index = index;
179
+ }
180
+ async load(id) {
181
+ const cached = this.loaded.get(id);
182
+ if (cached !== undefined)
183
+ return cached;
184
+ const value = await this.read(id);
185
+ this.loaded.set(id, value);
186
+ return value;
187
+ }
188
+ async read(id) {
189
+ const pkg = this.index.packages.find((p) => p.id === id);
190
+ if (pkg === undefined || pkg.manifest === null)
191
+ return null;
192
+ const manifest = pkg.manifest;
193
+ const documents = new Map();
194
+ for (const [key, kind] of [
195
+ ["flows", "flow"],
196
+ ["screens", "screen"],
197
+ ]) {
198
+ for (const entry of manifest.catalog[key]) {
199
+ const absolute = join(this.workspace, pkg.path, entry.path);
200
+ if (!(await this.fs.exists(absolute)))
201
+ continue;
202
+ const parsed = validateDesignArtifact(await this.fs.readText(absolute), kind, entry.path);
203
+ if (parsed.ok && parsed.value !== null)
204
+ documents.set(entry.path, parsed.value);
205
+ }
206
+ }
207
+ return {
208
+ manifest,
209
+ records: await this.readRecords(manifest, pkg.path),
210
+ read: (path) => documents.get(path) ?? null,
211
+ };
212
+ }
213
+ /**
214
+ * Records are read through the paths the MANIFEST indexes, never by globbing
215
+ * `governance/`: the manifest is the normative index, and a file it does not
216
+ * index is not a decision anybody registered.
217
+ */
218
+ async readRecords(manifest, packagePath) {
219
+ const records = [];
220
+ for (const [entries, validate] of [
221
+ [manifest.governance.reviews, validateDesignReview],
222
+ [manifest.governance.revocations, validateDesignRevocation],
223
+ ]) {
224
+ for (const entry of entries) {
225
+ const absolute = join(this.workspace, packagePath, entry.path);
226
+ if (!(await this.fs.exists(absolute)))
227
+ continue;
228
+ let parsed;
229
+ try {
230
+ parsed = JSON.parse(await this.fs.readText(absolute));
231
+ }
232
+ catch {
233
+ continue;
234
+ }
235
+ // An invalid record is NOT a decision: a malformed revocation must not
236
+ // block, and a malformed approval must not approve. Package validation
237
+ // is where its shape gets reported.
238
+ const validation = validate(parsed, entry.path);
239
+ if (validation.ok && validation.value !== null)
240
+ records.push(validation.value);
241
+ }
242
+ }
243
+ return records;
244
+ }
245
+ }
246
+ //# sourceMappingURL=design-gate-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-gate-service.js","sourceRoot":"","sources":["../../../src/application/design/design-gate-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { join } from "node:path";
2
+ import { parseSpecDesignReferences, parseTaskDesignReferences, } from "../../domain/design/reference.js";
3
+ import { readDesignIndex } from "./design-index-service.js";
4
+ import { resolveBaselineReference } from "./design-resolver-service.js";
5
+ export const EMPTY_DESIGN_GRAPH = {
6
+ root: "docs/designs",
7
+ packages: [],
8
+ references: [],
9
+ counts: { valid: 0, stale: 0, missing: 0, orphaned: 0 },
10
+ };
11
+ /**
12
+ * Never throws on a reachable workspace: a document that cannot be read
13
+ * contributes no references rather than tanking the whole dashboard — the same
14
+ * degradation rule the index it feeds already follows.
15
+ */
16
+ export async function buildDesignGraph(fs, workspace, documents) {
17
+ const index = await readDesignIndex(fs, workspace);
18
+ if (index.packages.length === 0 && documents.length === 0)
19
+ return EMPTY_DESIGN_GRAPH;
20
+ const references = [];
21
+ for (const document of documents) {
22
+ let text;
23
+ try {
24
+ text = await fs.readText(join(workspace, document.file));
25
+ }
26
+ catch {
27
+ continue;
28
+ }
29
+ const declared = parseSpecDesignReferences(text, document.file);
30
+ if (declared.references.length === 0)
31
+ continue;
32
+ const roots = parseTaskDesignReferences(text, document.file).references.map((r) => r.raw);
33
+ for (const reference of declared.references) {
34
+ references.push(edge(index, document, reference, roots));
35
+ }
36
+ }
37
+ const packages = statedPackages(index, references);
38
+ return {
39
+ root: index.root,
40
+ packages,
41
+ references,
42
+ counts: {
43
+ valid: references.filter((r) => r.state === "valid").length,
44
+ stale: references.filter((r) => r.state === "stale").length,
45
+ missing: references.filter((r) => r.state === "missing").length,
46
+ orphaned: packages.filter((p) => p.state === "orphaned").length,
47
+ },
48
+ };
49
+ }
50
+ /** One `document → baseline` edge, with the state that resolution gave it. */
51
+ function edge(index, document, reference, roots) {
52
+ const resolved = resolveBaselineReference(index, reference, document.file);
53
+ return {
54
+ from: document.file,
55
+ kind: document.kind,
56
+ baseline: `${reference.baseline.package}@r${reference.baseline.revision}`,
57
+ roots: roots.filter((raw) => raw.startsWith(`${reference.baseline.package}@`)),
58
+ ...(resolved.ok
59
+ ? {
60
+ state: resolved.value.hint,
61
+ package_path: resolved.value.package_path,
62
+ detail: resolved.value.hint === "stale"
63
+ ? `el hint apunta a '${resolved.value.declared_hint}' y hoy vive en '${resolved.value.path}'`
64
+ : null,
65
+ }
66
+ : {
67
+ state: "missing",
68
+ package_path: null,
69
+ detail: `${resolved.failure.message} → ${resolved.failure.action}`,
70
+ }),
71
+ };
72
+ }
73
+ function statedPackages(index, references) {
74
+ // A package is referenced when some document resolved AGAINST it — by
75
+ // identity, not by path: a stale hint still means somebody depends on it.
76
+ const referenced = new Set(references.filter((r) => r.state !== "missing").map((r) => r.baseline.split("@")[0]));
77
+ return index.packages.map((pkg) => ({
78
+ id: pkg.id,
79
+ path: pkg.path,
80
+ current_revision: pkg.current_baseline?.revision ?? null,
81
+ state: pkg.id !== null && referenced.has(pkg.id) ? "referenced" : "orphaned",
82
+ ok: pkg.ok,
83
+ }));
84
+ }
85
+ //# sourceMappingURL=design-graph-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-graph-service.js","sourceRoot":"","sources":["../../../src/application/design/design-graph-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ import { join } from "node:path";
2
+ import { DESIGNS_DIR, DESIGN_MANIFEST_FILE, validateDesignManifest, } from "../../domain/design/manifest.js";
3
+ import { isRecord } from "../../domain/design/validation.js";
4
+ export async function readDesignIndex(fs, workspace) {
5
+ const rootAbs = join(workspace, DESIGNS_DIR);
6
+ const index = { root: DESIGNS_DIR, packages: [], failures: [] };
7
+ if (!(await fs.exists(rootAbs)))
8
+ return index;
9
+ // "Moving the dossier WITHIN docs/designs/" includes moving it into a
10
+ // subfolder, so discovery descends. A directory that is itself a package
11
+ // stops the descent: a package never contains another one.
12
+ await collect(fs, rootAbs, "", index.packages);
13
+ index.packages.sort((a, b) => (a.id ?? a.path).localeCompare(b.id ?? b.path));
14
+ index.failures = findDuplicateIds(index.packages);
15
+ return index;
16
+ }
17
+ /** Resolve by identity. The caller never passes a path — that is the point. */
18
+ export function resolveDesignPackage(index, id) {
19
+ return index.packages.find((p) => p.id === id) ?? null;
20
+ }
21
+ /** Depth-first walk under `docs/designs/`, stopping at each package. */
22
+ async function collect(fs, rootAbs, relative, out) {
23
+ const here = relative.length === 0 ? rootAbs : join(rootAbs, relative);
24
+ for (const entry of await fs.list(here)) {
25
+ // `dir` only, and `list` does not follow links: a symlink under
26
+ // `docs/designs/` reads as `other`, so it can never pull a manifest — and an
27
+ // identity — in from outside the workspace.
28
+ if (entry.type !== "dir")
29
+ continue;
30
+ const folder = relative.length === 0 ? entry.name : `${relative}/${entry.name}`;
31
+ if (await fs.exists(join(rootAbs, folder, DESIGN_MANIFEST_FILE))) {
32
+ out.push(await readPackage(fs, rootAbs, folder));
33
+ continue;
34
+ }
35
+ // A folder that holds packages is a legitimate grouping. A LEAF with no
36
+ // manifest is not: it sits in the design taxonomy and is nothing.
37
+ const before = out.length;
38
+ await collect(fs, rootAbs, folder, out);
39
+ if (out.length === before && !(await hasSubdirectory(fs, join(rootAbs, folder)))) {
40
+ out.push(await readPackage(fs, rootAbs, folder));
41
+ }
42
+ }
43
+ }
44
+ async function hasSubdirectory(fs, dir) {
45
+ return (await fs.list(dir)).some((e) => e.type === "dir");
46
+ }
47
+ async function readPackage(fs, rootAbs, folder) {
48
+ const path = `${DESIGNS_DIR}/${folder}`;
49
+ const manifestPath = `${path}/${DESIGN_MANIFEST_FILE}`;
50
+ const base = {
51
+ id: null,
52
+ title: null,
53
+ path,
54
+ manifest_path: manifestPath,
55
+ declared_id: null,
56
+ current_baseline: null,
57
+ manifest: null,
58
+ ok: false,
59
+ failures: [],
60
+ };
61
+ const manifestAbs = join(rootAbs, folder, DESIGN_MANIFEST_FILE);
62
+ if (!(await fs.exists(manifestAbs))) {
63
+ return {
64
+ ...base,
65
+ failures: [
66
+ {
67
+ code: "DESIGN_MANIFEST_MISSING",
68
+ artifact: manifestPath,
69
+ message: `'${path}' está bajo ${DESIGNS_DIR}/ y no tiene ${DESIGN_MANIFEST_FILE}`,
70
+ action: `creá su manifest, o movéla fuera de ${DESIGNS_DIR}/ si no es un package`,
71
+ },
72
+ ],
73
+ };
74
+ }
75
+ let parsed;
76
+ try {
77
+ parsed = JSON.parse(await fs.readText(manifestAbs));
78
+ }
79
+ catch (err) {
80
+ return {
81
+ ...base,
82
+ failures: [
83
+ {
84
+ code: "DESIGN_MANIFEST_UNREADABLE",
85
+ artifact: manifestPath,
86
+ message: `no se pudo leer el manifest: ${err instanceof Error ? err.message : String(err)}`,
87
+ action: "reparalo como un único objeto JSON válido",
88
+ },
89
+ ],
90
+ };
91
+ }
92
+ const declared = isRecord(parsed) && typeof parsed.id === "string" ? parsed.id : null;
93
+ const validation = validateDesignManifest(parsed, manifestPath);
94
+ if (!validation.ok || validation.value === null) {
95
+ return { ...base, declared_id: declared, failures: validation.failures };
96
+ }
97
+ return { ...base, declared_id: declared, ...project(validation.value), ok: true };
98
+ }
99
+ function project(manifest) {
100
+ return {
101
+ id: manifest.id,
102
+ title: manifest.title,
103
+ current_baseline: manifest.current_baseline,
104
+ manifest,
105
+ };
106
+ }
107
+ /**
108
+ * Two packages claiming one identity break every reference to it, so the index
109
+ * reports it once per identity naming both locations — not once per package,
110
+ * which would read as two unrelated problems.
111
+ */
112
+ function findDuplicateIds(packages) {
113
+ const byId = new Map();
114
+ for (const pkg of packages) {
115
+ if (pkg.id === null)
116
+ continue;
117
+ byId.set(pkg.id, [...(byId.get(pkg.id) ?? []), pkg.path]);
118
+ }
119
+ const failures = [];
120
+ for (const [id, paths] of byId) {
121
+ if (paths.length < 2)
122
+ continue;
123
+ failures.push({
124
+ code: "DESIGN_ID_DUPLICATE",
125
+ artifact: paths.join(", "),
126
+ message: `${id} está declarado por ${paths.length} packages`,
127
+ action: "una identidad pertenece a un solo package: cambiá el id de los demás",
128
+ });
129
+ }
130
+ return failures;
131
+ }
132
+ //# sourceMappingURL=design-index-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-index-service.js","sourceRoot":"","sources":["../../../src/application/design/design-index-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAEL,WAAW,EACX,oBAAoB,EAGpB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AA4C7D,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAkB,EAAE,SAAiB;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7E,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9C,sEAAsE;IACtE,yEAAyE;IACzE,2DAA2D;IAC3D,MAAM,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE/C,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,KAAK,CAAC,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,KAAkB,EAAE,EAAU;IACjE,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC;AAED,wEAAwE;AACxE,KAAK,UAAU,OAAO,CACpB,EAAkB,EAClB,OAAe,EACf,QAAgB,EAChB,GAAyB;IAEzB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACvE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,gEAAgE;QAChE,6EAA6E;QAC7E,4CAA4C;QAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK;YAAE,SAAS;QACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAChF,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YACjD,SAAS;QACX,CAAC;QACD,wEAAwE;QACxE,kEAAkE;QAClE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QAC1B,MAAM,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACjF,GAAG,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,EAAkB,EAAE,GAAW;IAC5D,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,EAAkB,EAClB,OAAe,EACf,MAAc;IAEd,MAAM,IAAI,GAAG,GAAG,WAAW,IAAI,MAAM,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,GAAG,IAAI,IAAI,oBAAoB,EAAE,CAAC;IACvD,MAAM,IAAI,GAAuB;QAC/B,EAAE,EAAE,IAAI;QACR,KAAK,EAAE,IAAI;QACX,IAAI;QACJ,aAAa,EAAE,YAAY;QAC3B,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,IAAI;QACtB,QAAQ,EAAE,IAAI;QACd,EAAE,EAAE,KAAK;QACT,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAChE,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,yBAAyB;oBAC/B,QAAQ,EAAE,YAAY;oBACtB,OAAO,EAAE,IAAI,IAAI,eAAe,WAAW,gBAAgB,oBAAoB,EAAE;oBACjF,MAAM,EAAE,uCAAuC,WAAW,uBAAuB;iBAClF;aACF;SACF,CAAC;IACJ,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,GAAG,IAAI;YACP,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,4BAA4B;oBAClC,QAAQ,EAAE,YAAY;oBACtB,OAAO,EAAE,gCAAgC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;oBAC3F,MAAM,EAAE,2CAA2C;iBACpD;aACF;SACF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACtF,MAAM,UAAU,GAAG,sBAAsB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACpF,CAAC;AAED,SAAS,OAAO,CACd,QAAwB;IAExB,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;QAC3C,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,QAA8B;IACtD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAoB,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,GAAG,CAAC,EAAE,KAAK,IAAI;YAAE,SAAS;QAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC/B,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,qBAAqB;YAC3B,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;YAC1B,OAAO,EAAE,GAAG,EAAE,uBAAuB,KAAK,CAAC,MAAM,WAAW;YAC5D,MAAM,EAAE,sEAAsE;SAC/E,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}