@tacuchi/agent-workflow-cli 21.0.0 → 21.3.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 (170) hide show
  1. package/README.md +3 -2
  2. package/dist/adapters/git-cli.js +12 -7
  3. package/dist/adapters/git-cli.js.map +1 -1
  4. package/dist/application/capability/compose.js +161 -0
  5. package/dist/application/capability/compose.js.map +1 -0
  6. package/dist/application/capability/descriptor-loader.js +109 -0
  7. package/dist/application/capability/descriptor-loader.js.map +1 -0
  8. package/dist/application/capability/design-handler.js +299 -0
  9. package/dist/application/capability/design-handler.js.map +1 -0
  10. package/dist/application/capability/dispatcher.js +312 -0
  11. package/dist/application/capability/dispatcher.js.map +1 -0
  12. package/dist/application/capability/durable-effect.js +220 -0
  13. package/dist/application/capability/durable-effect.js.map +1 -0
  14. package/dist/application/capability/installed-inventory.js +168 -0
  15. package/dist/application/capability/installed-inventory.js.map +1 -0
  16. package/dist/application/capability/readiness.js +204 -0
  17. package/dist/application/capability/readiness.js.map +1 -0
  18. package/dist/application/capability/resolution.js +264 -0
  19. package/dist/application/capability/resolution.js.map +1 -0
  20. package/dist/application/capability/wrapper.js +195 -0
  21. package/dist/application/capability/wrapper.js.map +1 -0
  22. package/dist/application/context/manifest.js +11 -5
  23. package/dist/application/context/manifest.js.map +1 -1
  24. package/dist/application/context/measure.js +5 -2
  25. package/dist/application/context/measure.js.map +1 -1
  26. package/dist/application/context/plan-service.js +6 -6
  27. package/dist/application/context/plan-service.js.map +1 -1
  28. package/dist/application/design/design-bundle-service.js +148 -0
  29. package/dist/application/design/design-bundle-service.js.map +1 -0
  30. package/dist/application/design/design-proposal-service.js +69 -0
  31. package/dist/application/design/design-proposal-service.js.map +1 -0
  32. package/dist/application/design/design-publish-service.js +275 -7
  33. package/dist/application/design/design-publish-service.js.map +1 -1
  34. package/dist/application/design/design-record-service.js +100 -0
  35. package/dist/application/design/design-record-service.js.map +1 -0
  36. package/dist/application/flow/advance.js +533 -0
  37. package/dist/application/flow/advance.js.map +1 -0
  38. package/dist/application/flow/flow-service.js +65 -0
  39. package/dist/application/flow/flow-service.js.map +1 -0
  40. package/dist/application/flow/run-projection.js +80 -0
  41. package/dist/application/flow/run-projection.js.map +1 -0
  42. package/dist/application/flow/run-state-service.js +107 -0
  43. package/dist/application/flow/run-state-service.js.map +1 -0
  44. package/dist/application/flow/submit.js +423 -0
  45. package/dist/application/flow/submit.js.map +1 -0
  46. package/dist/application/markdown.js +16 -2
  47. package/dist/application/markdown.js.map +1 -1
  48. package/dist/application/resume-service.js +23 -10
  49. package/dist/application/resume-service.js.map +1 -1
  50. package/dist/application/self/hooks-toml.js +137 -17
  51. package/dist/application/self/hooks-toml.js.map +1 -1
  52. package/dist/application/self/host-states.js +87 -1
  53. package/dist/application/self/host-states.js.map +1 -1
  54. package/dist/application/self/install-hooks.js +62 -6
  55. package/dist/application/self/install-hooks.js.map +1 -1
  56. package/dist/application/self/install-skill.js +37 -6
  57. package/dist/application/self/install-skill.js.map +1 -1
  58. package/dist/application/self/uninstall.js +21 -0
  59. package/dist/application/self/uninstall.js.map +1 -1
  60. package/dist/application/skills-resolver-service.js +8 -2
  61. package/dist/application/skills-resolver-service.js.map +1 -1
  62. package/dist/application/status-service.js +4 -1
  63. package/dist/application/status-service.js.map +1 -1
  64. package/dist/application/workline-index-service.js +15 -2
  65. package/dist/application/workline-index-service.js.map +1 -1
  66. package/dist/application/workspace-init-service.js +13 -1
  67. package/dist/application/workspace-init-service.js.map +1 -1
  68. package/dist/cli/commands/capability.js +182 -0
  69. package/dist/cli/commands/capability.js.map +1 -0
  70. package/dist/cli/commands/flow.js +71 -0
  71. package/dist/cli/commands/flow.js.map +1 -0
  72. package/dist/cli/commands/index.js +4 -0
  73. package/dist/cli/commands/index.js.map +1 -1
  74. package/dist/cli/commands/skills.js +55 -2
  75. package/dist/cli/commands/skills.js.map +1 -1
  76. package/dist/cli/commands/status.js +5 -0
  77. package/dist/cli/commands/status.js.map +1 -1
  78. package/dist/cli/help-groups.js +6 -0
  79. package/dist/cli/help-groups.js.map +1 -1
  80. package/dist/cli/parser.js +6 -0
  81. package/dist/cli/parser.js.map +1 -1
  82. package/dist/cli/tui/components/host-admin-section.js +14 -2
  83. package/dist/cli/tui/components/host-admin-section.js.map +1 -1
  84. package/dist/cli/tui/data/workflow-content.js +13 -1
  85. package/dist/cli/tui/data/workflow-content.js.map +1 -1
  86. package/dist/cli/tui/tabs/workflow-tab.js +8 -1
  87. package/dist/cli/tui/tabs/workflow-tab.js.map +1 -1
  88. package/dist/domain/capability/descriptor.js +553 -0
  89. package/dist/domain/capability/descriptor.js.map +1 -0
  90. package/dist/domain/capability/effects.js +90 -0
  91. package/dist/domain/capability/effects.js.map +1 -0
  92. package/dist/domain/capability/protocol.js +494 -0
  93. package/dist/domain/capability/protocol.js.map +1 -0
  94. package/dist/domain/contract-reader.js +84 -0
  95. package/dist/domain/contract-reader.js.map +1 -0
  96. package/dist/domain/design/adapter.js +161 -0
  97. package/dist/domain/design/adapter.js.map +1 -0
  98. package/dist/domain/design/artifact.js +148 -4
  99. package/dist/domain/design/artifact.js.map +1 -1
  100. package/dist/domain/design/capability.js +263 -4
  101. package/dist/domain/design/capability.js.map +1 -1
  102. package/dist/domain/design/direct.js +108 -0
  103. package/dist/domain/design/direct.js.map +1 -0
  104. package/dist/domain/design/external-send.js +65 -0
  105. package/dist/domain/design/external-send.js.map +1 -0
  106. package/dist/domain/design/maturity.js +71 -0
  107. package/dist/domain/design/maturity.js.map +1 -1
  108. package/dist/domain/design/offline.js +92 -0
  109. package/dist/domain/design/offline.js.map +1 -0
  110. package/dist/domain/design/profiles.js +212 -0
  111. package/dist/domain/design/profiles.js.map +1 -0
  112. package/dist/domain/design/proposal.js +234 -0
  113. package/dist/domain/design/proposal.js.map +1 -0
  114. package/dist/domain/design/render-bundle.js +0 -0
  115. package/dist/domain/design/render-bundle.js.map +1 -0
  116. package/dist/domain/design/rendition.js +472 -0
  117. package/dist/domain/design/rendition.js.map +1 -0
  118. package/dist/domain/design/sources.js +180 -0
  119. package/dist/domain/design/sources.js.map +1 -0
  120. package/dist/domain/design/validation.js +12 -68
  121. package/dist/domain/design/validation.js.map +1 -1
  122. package/dist/domain/design/visual-evidence.js +155 -0
  123. package/dist/domain/design/visual-evidence.js.map +1 -0
  124. package/dist/domain/flow/answer.js +459 -0
  125. package/dist/domain/flow/answer.js.map +1 -0
  126. package/dist/domain/flow/authority.js +2338 -0
  127. package/dist/domain/flow/authority.js.map +1 -0
  128. package/dist/domain/flow/authorization.js +62 -0
  129. package/dist/domain/flow/authorization.js.map +1 -0
  130. package/dist/domain/flow/directive.js +421 -0
  131. package/dist/domain/flow/directive.js.map +1 -0
  132. package/dist/domain/flow/rules.js +140 -0
  133. package/dist/domain/flow/rules.js.map +1 -0
  134. package/dist/domain/flow/run-state.js +317 -0
  135. package/dist/domain/flow/run-state.js.map +1 -0
  136. package/dist/domain/harnesses.js +124 -4
  137. package/dist/domain/harnesses.js.map +1 -1
  138. package/dist/domain/host-verification.js +8 -8
  139. package/dist/domain/skills.js +13 -14
  140. package/dist/domain/skills.js.map +1 -1
  141. package/dist/domain/structured-choice-stamp.js +106 -0
  142. package/dist/domain/structured-choice-stamp.js.map +1 -0
  143. package/package.json +1 -1
  144. package/skills/w/SKILL.md +5 -5
  145. package/skills/w/context/MANIFEST.json +42 -1
  146. package/skills/w/harness/HARNESS.md +30 -4
  147. package/skills/w/loops/CHASSIS.md +11 -20
  148. package/skills/w/loops/CODE-POLICIES.md +9 -15
  149. package/skills/w/loops/plan-exec-loop/LOOP.md +11 -13
  150. package/skills/w/loops/plan-new-loop/LOOP.md +6 -4
  151. package/skills/w/loops/plan-refine-loop/LOOP.md +5 -3
  152. package/skills/w/loops/quick-loop/LOOP.md +18 -26
  153. package/skills/w/loops/spec-refine-loop/LOOP.md +14 -18
  154. package/skills/w/modules/COMPACTION.md +2 -6
  155. package/skills/w/modules/DB-SCRIPTS-ONLY.md +2 -0
  156. package/skills/w/modules/DESIGN-REFERENCES.md +15 -11
  157. package/skills/w/modules/IDEATION-GATE.md +3 -3
  158. package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +17 -36
  159. package/skills/w/modules/PLAN-INPUT.md +5 -3
  160. package/skills/w/modules/PLAN-REFINE-SPLIT.md +3 -1
  161. package/skills/w/modules/PLAN-SPLIT-GATE.md +7 -5
  162. package/skills/w/modules/PROMPT-CONTINUITY.md +3 -1
  163. package/skills/w/modules/SPEC-CHANGE-SHAPE.md +4 -4
  164. package/skills/w/roles/README.md +2 -0
  165. package/skills/w/roles/design/CONTRACT.md +80 -0
  166. package/skills/w/roles/design/ROLE.md +7 -0
  167. package/skills/w/schemas/capability-descriptor.schema.json +260 -0
  168. package/skills/w/schemas/design/design-render-bundle.v1.schema.json +191 -0
  169. package/skills/w/schemas/design/design-rendition.v1.schema.json +232 -0
  170. package/skills/w/schemas/design/ui-screen.v1.schema.json +29 -1
@@ -0,0 +1,220 @@
1
+ /**
2
+ * The bridge from a capability attempt to the durable handshake that already
3
+ * exists — and the line that keeps the two from merging.
4
+ *
5
+ * `prepare → validate → apply` is how this repo previews, approves and writes.
6
+ * It is not a conversation, and a capability's attempts are not stages of it.
7
+ * The distinction is load-bearing: an operation that only reads, or an attempt
8
+ * that answers `needs_input`, must not manufacture a preview and an approval for
9
+ * something that will never be written. So this adapter is entered ONLY when an
10
+ * attempt is about to produce a durable effect, and it refuses otherwise.
11
+ *
12
+ * What it adds on top of the existing machinery is the four things that have to
13
+ * be true together before the first byte lands: the request is the one that was
14
+ * sealed, the candidate output is the one that was shown, the authorization
15
+ * covers the effect classes about to be exercised, and the base has not moved.
16
+ * Any of the four failing stops before `publishArtifacts` is called at all.
17
+ */
18
+ import { join } from "node:path";
19
+ import { withCwdLock } from "../lock-service.js";
20
+ import { SEMANTIC_PROTOCOL_VERSION, approvalDigest, semanticDigest, } from "../semantic-operation/protocol.js";
21
+ import { publishArtifacts } from "../semantic-operation/publish.js";
22
+ /**
23
+ * The one way to digest a base.
24
+ *
25
+ * Two conventions for "the digest of this file" is a comparison that fails for a
26
+ * reason nobody can see: prepare would seal one form and apply recompute the
27
+ * other, and every publication would look stale. Exported so both sides call the
28
+ * same function rather than each reaching for a hash.
29
+ */
30
+ export function baseDigest(text) {
31
+ return semanticDigest(text);
32
+ }
33
+ const DURABLE_CLASSES = [
34
+ "local_additive",
35
+ "mutate_overwrite",
36
+ "execute",
37
+ "network_external",
38
+ "destructive",
39
+ ];
40
+ export function prepareDurableEffect(input) {
41
+ const durable = input.authorization.planned.filter((c) => DURABLE_CLASSES.includes(c));
42
+ if (durable.length === 0) {
43
+ return {
44
+ ok: false,
45
+ failure: {
46
+ code: "CAPABILITY_EFFECT_NOT_DURABLE",
47
+ message: `'${input.request.operation}' no declara ningún efecto durable`,
48
+ action: "una operación read-only devuelve su resultado y no atraviesa preview ni aprobación",
49
+ },
50
+ };
51
+ }
52
+ if (input.authorization.denied.length > 0) {
53
+ const first = input.authorization.denied[0];
54
+ return {
55
+ ok: false,
56
+ failure: {
57
+ code: "CAPABILITY_EFFECT_DENIED",
58
+ message: `la política del host no admite el efecto '${first?.class}'`,
59
+ action: "quitá la operación o ajustá la política del host, que siempre prevalece",
60
+ },
61
+ };
62
+ }
63
+ if (input.artifacts.length === 0) {
64
+ return {
65
+ ok: false,
66
+ failure: {
67
+ code: "CAPABILITY_EFFECT_EMPTY",
68
+ message: "no hay ningún artefacto candidato que publicar",
69
+ action: "producí el output antes de preparar el efecto durable",
70
+ },
71
+ };
72
+ }
73
+ const response = asSemanticResponse(input.request, input.artifacts);
74
+ return {
75
+ ok: true,
76
+ plan: {
77
+ capability: input.request.capability,
78
+ operation: input.request.operation,
79
+ request_digest: input.request.request_digest,
80
+ semantic_inputs_digest: input.request.semantic_inputs_digest,
81
+ artifacts: input.artifacts,
82
+ preview: input.artifacts.map((a) => ({
83
+ path: a.path,
84
+ bytes: Buffer.byteLength(a.content, "utf8"),
85
+ overwrite: a.overwrite === true,
86
+ })),
87
+ approval_digest: approvalDigest(response),
88
+ requires_approval: [...input.authorization.needsPreflight],
89
+ base: input.base ?? null,
90
+ },
91
+ };
92
+ }
93
+ /**
94
+ * The exact bytes proposed, in the shape the existing seal already understands.
95
+ *
96
+ * Reusing `approvalDigest` rather than inventing a capability-flavoured one is
97
+ * the whole point of the adapter: one seal over "what was approved is what gets
98
+ * written", not two that can disagree.
99
+ */
100
+ function asSemanticResponse(request, artifacts) {
101
+ return {
102
+ version: SEMANTIC_PROTOCOL_VERSION,
103
+ operation: `${request.capability}.${request.operation}`,
104
+ input_digest: request.semantic_inputs_digest,
105
+ state: "proposed",
106
+ artifacts: artifacts.map((a) => ({ path: a.path, content: a.content })),
107
+ };
108
+ }
109
+ export async function applyDurableEffect(fs, paths, input) {
110
+ const gate = checkApproval(input);
111
+ if (gate !== null)
112
+ return { ok: false, failure: gate, applied: [] };
113
+ const stale = await checkBase(fs, input);
114
+ if (stale !== null)
115
+ return { ok: false, failure: stale, applied: [] };
116
+ const outcome = await withCwdLock(fs, paths, async () => publishArtifacts(fs, input.root, input.plan.artifacts));
117
+ if ("error" in outcome) {
118
+ return {
119
+ ok: false,
120
+ failure: {
121
+ code: "CAPABILITY_EFFECT_LOCKED",
122
+ message: outcome.error,
123
+ action: "esperá a que se libere el lock del workspace y volvé a aplicar",
124
+ },
125
+ applied: [],
126
+ };
127
+ }
128
+ if (!outcome.ok) {
129
+ // `publishArtifacts` is all-or-nothing and rolls back, so nothing landed —
130
+ // and saying so explicitly is what makes the empty list a claim rather than
131
+ // an omission.
132
+ return {
133
+ ok: false,
134
+ failure: {
135
+ code: outcome.failure.code,
136
+ message: outcome.failure.message,
137
+ action: outcome.failure.action,
138
+ },
139
+ applied: [],
140
+ };
141
+ }
142
+ return {
143
+ ok: true,
144
+ result: {
145
+ written: outcome.value.written,
146
+ applied: [...new Set([...input.selfAuthorized, ...input.approval.granted])].filter((c) => DURABLE_CLASSES.includes(c)),
147
+ },
148
+ };
149
+ }
150
+ function checkApproval(input) {
151
+ if (input.approval.digest !== input.plan.approval_digest) {
152
+ return {
153
+ code: "CAPABILITY_APPROVAL_MISMATCH",
154
+ message: "lo aprobado no son los bytes que se van a escribir",
155
+ action: "volvé a preparar el efecto y aprobá la propuesta que se muestra",
156
+ };
157
+ }
158
+ const missing = input.plan.requires_approval.filter((c) => !input.approval.granted.includes(c));
159
+ if (missing.length > 0) {
160
+ return {
161
+ code: "CAPABILITY_APPROVAL_MISSING",
162
+ message: `falta aprobación visible para: ${missing.join(", ")}`,
163
+ action: "mostrá datos, destino y efecto, y pedí aprobación antes de aplicar",
164
+ };
165
+ }
166
+ return null;
167
+ }
168
+ /**
169
+ * The base has to still be the base.
170
+ *
171
+ * A candidate output computed from revision N and published on top of revision
172
+ * N+1 is a silent overwrite of whatever happened in between — the reason the
173
+ * compare-and-swap exists at all. Re-read at apply, never trusted from prepare.
174
+ */
175
+ async function checkBase(fs, input) {
176
+ const base = input.plan.base;
177
+ if (base === null)
178
+ return null;
179
+ const absolute = join(input.root, base.path);
180
+ if (!(await fs.exists(absolute))) {
181
+ return {
182
+ code: "CAPABILITY_BASE_GONE",
183
+ message: `la base '${base.path}' ya no existe`,
184
+ action: "volvé a preparar la operación sobre la base vigente",
185
+ };
186
+ }
187
+ const current = baseDigest(await fs.readText(absolute));
188
+ if (current !== base.digest) {
189
+ return {
190
+ code: "CAPABILITY_BASE_STALE",
191
+ message: `'${base.path}' cambió después de preparar la propuesta`,
192
+ action: "volvé a preparar la operación sobre la base vigente y revisá el resultado",
193
+ };
194
+ }
195
+ return null;
196
+ }
197
+ /**
198
+ * What to say when something broke or was cancelled AFTER an effect landed.
199
+ *
200
+ * The failure mode this closes is the comfortable one: reporting a cancellation
201
+ * as if nothing had happened, because the operation "did not finish". An
202
+ * external step that already left the machine cannot be un-left, so the honest
203
+ * report enumerates it and hands back the reconciliation to run.
204
+ */
205
+ export function reconcileAfterFailure(outcome, partial) {
206
+ if (partial.length === 0) {
207
+ return {
208
+ applied: [],
209
+ next_action: outcome === "cancelled"
210
+ ? "no se aplicó ningún efecto: podés volver a intentar cuando quieras"
211
+ : "no se aplicó ningún efecto: corregí la causa del fallo y volvé a intentar",
212
+ };
213
+ }
214
+ const detail = partial.map((p) => `${p.class}: ${p.what}`).join("; ");
215
+ return {
216
+ applied: [...new Set(partial.map((p) => p.class))],
217
+ next_action: `quedaron efectos aplicados que hay que reconciliar a mano — ${detail}`,
218
+ };
219
+ }
220
+ //# sourceMappingURL=durable-effect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durable-effect.js","sourceRoot":"","sources":["../../../src/application/capability/durable-effect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * What is ACTUALLY installed, as exact instances.
3
+ *
4
+ * The advisory check this replaces compared names. A name is not a thing that
5
+ * runs: two directories can both be called `design`, and picking one by scan
6
+ * order is a silent choice nobody made. So the unit here is an instance —
7
+ * name, scope, the locator of its `SKILL.md`, the locator of its descriptor, its
8
+ * version and a digest over its bytes — and the two failure modes are kept
9
+ * apart:
10
+ *
11
+ * - **Same name, same digest, several roots.** Equivalent replicas. Every
12
+ * locator is kept, because "which copy answered" is still a real question.
13
+ * - **Same name, different bytes.** `misconfigured`. Not a precedence puzzle to
14
+ * resolve — two different things are wearing one name, and no scan order makes
15
+ * that safe.
16
+ *
17
+ * Only skills that DECLARE a descriptor enter this inventory. An ambient skill —
18
+ * a linter, a writing convention — is installed and invisible here, which is the
19
+ * whole content of the opt-in.
20
+ */
21
+ import { createHash } from "node:crypto";
22
+ import { RETIRED_SKILL_IDENTITIES } from "../../domain/skills.js";
23
+ import { semanticDigest } from "../semantic-operation/protocol.js";
24
+ import { skillRoots } from "../skills-resolver-service.js";
25
+ import { loadDescriptor, readSkillHead } from "./descriptor-loader.js";
26
+ export async function buildCapabilityInventory(fs, env) {
27
+ const roots = skillRoots(env);
28
+ const candidates = [];
29
+ for (const root of roots) {
30
+ candidates.push(...(await scanRoot(fs, root)));
31
+ }
32
+ return { roots, capabilities: group(candidates) };
33
+ }
34
+ async function scanRoot(fs, root) {
35
+ if (!(await fs.exists(root)))
36
+ return [];
37
+ let entries;
38
+ try {
39
+ entries = await fs.list(root);
40
+ }
41
+ catch {
42
+ return [];
43
+ }
44
+ const found = [];
45
+ for (const entry of entries) {
46
+ if (entry.type !== "dir")
47
+ continue;
48
+ const head = await readSkillHead(fs, entry.path, entry.name);
49
+ // No readable head, or no claim at all: an ambient skill. It never becomes a
50
+ // capability by being installed, so it never enters the inventory.
51
+ if (head === null || head.locatorValue === null)
52
+ continue;
53
+ found.push(await candidateFor(fs, root, entry.path, head));
54
+ }
55
+ return found;
56
+ }
57
+ async function candidateFor(fs, root, skillDir, head) {
58
+ const location = {
59
+ scope: root,
60
+ skillDir,
61
+ skillMd: head.skillMd,
62
+ descriptorPath: null,
63
+ };
64
+ const base = { name: head.name, version: head.version, location, descriptor: null };
65
+ // A directory wearing a retired name is refused before its descriptor is even
66
+ // read: the name IS the identity, and honoring it would resurrect the alias
67
+ // the contract exists to close.
68
+ const retired = RETIRED_SKILL_IDENTITIES.get(head.name.toLowerCase());
69
+ if (retired !== undefined) {
70
+ return {
71
+ ...base,
72
+ digest: null,
73
+ failure: {
74
+ code: "CAPABILITY_NAME_RETIRED",
75
+ message: `'${head.name}' está retirado — ${retired}`,
76
+ action: "renombrá la skill al nombre vigente de la capacidad; no hay alias",
77
+ },
78
+ };
79
+ }
80
+ const load = await loadDescriptor(fs, skillDir, head);
81
+ if (load.state !== "loaded") {
82
+ return {
83
+ ...base,
84
+ digest: null,
85
+ failure: load.state === "invalid" ? load.failure : null,
86
+ };
87
+ }
88
+ return {
89
+ name: head.name,
90
+ version: head.version,
91
+ digest: await instanceDigest(fs, head.skillMd, load.loaded.digest),
92
+ location: { ...location, descriptorPath: load.loaded.path },
93
+ descriptor: load.loaded.descriptor,
94
+ failure: null,
95
+ };
96
+ }
97
+ /**
98
+ * The identity of the bytes that would run: the instruction file AND the
99
+ * contract it points at. Sealing only the descriptor would call two skills
100
+ * identical while their `SKILL.md` told the host to do different things.
101
+ */
102
+ async function instanceDigest(fs, skillMd, descriptorDigest) {
103
+ try {
104
+ const text = await fs.readText(skillMd);
105
+ return semanticDigest({
106
+ skill_md: createHash("sha256").update(text, "utf8").digest("hex"),
107
+ descriptor: descriptorDigest,
108
+ });
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ function group(candidates) {
115
+ const byName = new Map();
116
+ for (const candidate of candidates) {
117
+ byName.set(candidate.name, [...(byName.get(candidate.name) ?? []), candidate]);
118
+ }
119
+ const out = [];
120
+ for (const [name, copies] of byName) {
121
+ const locations = copies.map((c) => c.location);
122
+ const broken = copies.find((c) => c.failure !== null);
123
+ if (broken?.failure != null) {
124
+ out.push({
125
+ name,
126
+ version: broken.version,
127
+ digest: null,
128
+ locations,
129
+ descriptor: null,
130
+ state: "misconfigured",
131
+ failure: broken.failure,
132
+ });
133
+ continue;
134
+ }
135
+ const digests = [...new Set(copies.map((c) => c.digest))];
136
+ const first = copies[0];
137
+ if (digests.length > 1) {
138
+ out.push({
139
+ name,
140
+ version: first.version,
141
+ digest: null,
142
+ locations,
143
+ descriptor: null,
144
+ state: "misconfigured",
145
+ failure: {
146
+ code: "CAPABILITY_INSTANCE_COLLISION",
147
+ message: `hay ${copies.length} skills llamadas '${name}' con bytes distintos: ${locations.map((l) => l.skillDir).join(", ")}`,
148
+ action: "dejá una sola instalación de ese nombre, o renombrá la que no corresponde: no hay precedencia entre roots",
149
+ },
150
+ });
151
+ continue;
152
+ }
153
+ out.push({
154
+ name,
155
+ version: first.version,
156
+ digest: first.digest,
157
+ locations,
158
+ descriptor: first.descriptor,
159
+ state: "ready",
160
+ failure: null,
161
+ });
162
+ }
163
+ return out.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
164
+ }
165
+ export function findInstalled(inventory, name) {
166
+ return inventory.capabilities.find((c) => c.name === name) ?? null;
167
+ }
168
+ //# sourceMappingURL=installed-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installed-inventory.js","sourceRoot":"","sources":["../../../src/application/capability/installed-inventory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * What can be invoked here, in what state, and what to do about it.
3
+ *
4
+ * The check this replaces compared names and emitted advice. Readiness answers
5
+ * the question a person actually has — "can I use this right now, and if not,
6
+ * why?" — and every state carries its evidence and one next action, because a
7
+ * status with neither is a puzzle rather than a diagnosis.
8
+ *
9
+ * Two things are deliberately kept apart:
10
+ *
11
+ * - **Per exposure.** The direct entrypoint and the composed route fail
12
+ * independently. A foreign skill squatting the wrapper's name breaks `direct`
13
+ * and leaves `compose` running on the floor; collapsing them into one state
14
+ * would hide half of that.
15
+ * - **Per operation.** `off` blocks four operations of `design` and keeps
16
+ * `validate` alive. One state for the capability cannot express that.
17
+ *
18
+ * The invocation form is read from `HARNESSES` and never inferred. A host with
19
+ * no verified form says so instead of borrowing another host's syntax.
20
+ */
21
+ import { join } from "node:path";
22
+ import { HARNESSES } from "../../domain/harnesses.js";
23
+ import { classifyCapabilityBinding } from "../../domain/skills.js";
24
+ import { resolveSkills } from "../skills-resolver-service.js";
25
+ import { capabilityHandler, registeredCapabilities } from "./dispatcher.js";
26
+ import { buildCapabilityInventory } from "./installed-inventory.js";
27
+ import { resolveCapability } from "./resolution.js";
28
+ import { inspectCapabilityDirVia } from "./wrapper.js";
29
+ export async function capabilityReadiness(input) {
30
+ const skills = await resolveSkills(input.fs, input.paths);
31
+ const inventory = await buildCapabilityInventory(input.fs, input.env);
32
+ const reports = [];
33
+ for (const name of registeredCapabilities()) {
34
+ const handler = capabilityHandler(name);
35
+ if (handler === null)
36
+ continue;
37
+ const slot = skills.skills[name];
38
+ const binding = slot === undefined
39
+ ? { state: "floor_and_improvements", reason: null, action: null }
40
+ : classifyCapabilityBinding(slot, name);
41
+ const resolution = resolveCapability({ descriptor: handler.descriptor, binding, inventory });
42
+ reports.push(await reportFor(input, handler.descriptor, resolution, inventory, {
43
+ state: resolution.state,
44
+ reason: resolution.reason,
45
+ action: resolution.action,
46
+ }));
47
+ }
48
+ return reports;
49
+ }
50
+ async function reportFor(input, descriptor, resolution, inventory, verdict) {
51
+ const direct = await directVerdict(input, descriptor, verdict);
52
+ return {
53
+ capability: descriptor.name,
54
+ contract_version: descriptor.contract_version,
55
+ purpose: descriptor.purpose,
56
+ exposure: descriptor.exposure,
57
+ ...verdict,
58
+ floor: {
59
+ builtin: descriptor.floor.builtin,
60
+ kind: descriptor.floor.kind,
61
+ running: resolution.floor,
62
+ },
63
+ instance: resolution.selection[0] === undefined
64
+ ? null
65
+ : {
66
+ name: resolution.selection[0].name,
67
+ scope: resolution.selection[0].scope,
68
+ locator: resolution.selection[0].locator,
69
+ version: resolution.selection[0].version,
70
+ digest: resolution.selection[0].digest,
71
+ },
72
+ invocation: invocationFor(input.host, descriptor.name),
73
+ exposures: {
74
+ direct: descriptor.exposure.includes("direct")
75
+ ? direct
76
+ : { state: "unavailable", reason: "la capacidad no expone la ruta directa", action: null },
77
+ compose: descriptor.exposure.includes("compose")
78
+ ? verdict
79
+ : {
80
+ state: "unavailable",
81
+ reason: "la capacidad no expone la ruta compuesta",
82
+ action: null,
83
+ },
84
+ },
85
+ operations: descriptor.operations.map((op) => {
86
+ const availability = resolution.operations.find((o) => o.operation === op.name);
87
+ const blocked = availability !== undefined && !availability.available;
88
+ return {
89
+ operation: op.name,
90
+ exposure: op.exposure,
91
+ workspace: op.workspace,
92
+ effects: op.effects.map((e) => e.class),
93
+ // The capability being `disabled` does NOT make the operation `off`
94
+ // spared disabled too: saying so would erase exactly the consumption
95
+ // `off` is required to preserve.
96
+ state: blocked ? "disabled" : availableState(verdict, resolution.floor),
97
+ reason: blocked ? availability.reason : verdict.reason,
98
+ action: blocked ? (resolution.action ?? null) : verdict.action,
99
+ };
100
+ }),
101
+ improvements: inventory.capabilities
102
+ .filter((c) => c.name !== descriptor.name)
103
+ .map((c) => eligibility(c, descriptor)),
104
+ };
105
+ }
106
+ /**
107
+ * The direct route lives or dies by a real directory on disk.
108
+ *
109
+ * A capability can be perfectly resolved and still be unreachable directly
110
+ * because nobody installed the wrapper — or because someone else's skill holds
111
+ * the name. Both are states of the ENTRYPOINT, not of the capability, so they
112
+ * are reported here and nowhere else.
113
+ */
114
+ async function directVerdict(input, descriptor, verdict) {
115
+ const harness = HARNESSES.find((h) => h.id === input.host);
116
+ if (harness === undefined || harness.invocation === null) {
117
+ return {
118
+ state: "unavailable",
119
+ reason: `no hay una forma de invocación verificada para el host '${input.host}'`,
120
+ action: "usá la ruta compuesta desde un flow, o instalá en un host soportado",
121
+ };
122
+ }
123
+ const root = join(input.env.homeDir(), ...(harness.skillsDirs[0]?.split("/") ?? []));
124
+ const ownership = await inspectCapabilityDirVia(input.fs, join(root, descriptor.name));
125
+ if (ownership.state === "foreign") {
126
+ return {
127
+ state: "misconfigured",
128
+ reason: ownership.why,
129
+ action: `renombrá o quitá esa skill y reinstalá con 'aw self install-skill'`,
130
+ };
131
+ }
132
+ if (ownership.state === "absent") {
133
+ return {
134
+ state: "unavailable",
135
+ reason: `no hay un wrapper '${descriptor.name}' instalado en ${root}`,
136
+ action: "instalalo con 'aw self install-skill'",
137
+ };
138
+ }
139
+ return verdict;
140
+ }
141
+ /** What an AVAILABLE operation's state is when the capability itself is off. */
142
+ function availableState(verdict, floorRunning) {
143
+ if (verdict.state !== "disabled")
144
+ return verdict.state;
145
+ return floorRunning ? "ready" : "unavailable";
146
+ }
147
+ function invocationFor(host, name) {
148
+ const harness = HARNESSES.find((h) => h.id === host);
149
+ const invocation = harness?.invocation ?? null;
150
+ if (invocation === null) {
151
+ return {
152
+ host,
153
+ kind: "unavailable",
154
+ form: null,
155
+ // Saying "unavailable" is the honest answer. Printing another host's
156
+ // syntax would send a person to type something that does nothing.
157
+ note: `no hay una forma de invocación verificada para '${host}'`,
158
+ };
159
+ }
160
+ return {
161
+ host,
162
+ kind: invocation.kind,
163
+ form: invocation.template.replace("<name>", name),
164
+ note: invocation.note,
165
+ };
166
+ }
167
+ function eligibility(installed, descriptor) {
168
+ const improves = installed.descriptor?.compatibility.improves ?? null;
169
+ if (installed.state === "misconfigured") {
170
+ return {
171
+ name: installed.name,
172
+ digest: null,
173
+ improves: null,
174
+ eligible: false,
175
+ why: installed.failure?.message ?? "instancia no identificable",
176
+ };
177
+ }
178
+ if (improves === null || improves.capability !== descriptor.name) {
179
+ return {
180
+ name: installed.name,
181
+ digest: installed.digest,
182
+ improves: improves?.capability ?? null,
183
+ eligible: false,
184
+ why: `no declara mejorar '${descriptor.name}'`,
185
+ };
186
+ }
187
+ if (improves.contract_version !== descriptor.contract_version) {
188
+ return {
189
+ name: installed.name,
190
+ digest: installed.digest,
191
+ improves: improves.capability,
192
+ eligible: false,
193
+ why: `habla la versión de contrato ${improves.contract_version}`,
194
+ };
195
+ }
196
+ return {
197
+ name: installed.name,
198
+ digest: installed.digest,
199
+ improves: improves.capability,
200
+ eligible: true,
201
+ why: null,
202
+ };
203
+ }
204
+ //# sourceMappingURL=readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../../../src/application/capability/readiness.ts"],"names":[],"mappings":"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"}