@tacuchi/agent-workflow-cli 25.1.2 → 25.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 (133) hide show
  1. package/README.md +3 -1
  2. package/dist/adapters/node-process.js +35 -0
  3. package/dist/adapters/node-process.js.map +1 -1
  4. package/dist/application/amend-service.js +393 -0
  5. package/dist/application/amend-service.js.map +1 -0
  6. package/dist/application/decision-note-service.js +20 -3
  7. package/dist/application/decision-note-service.js.map +1 -1
  8. package/dist/application/doctor/actions.js +158 -0
  9. package/dist/application/doctor/actions.js.map +1 -0
  10. package/dist/application/doctor/apply.js +399 -0
  11. package/dist/application/doctor/apply.js.map +1 -0
  12. package/dist/application/doctor/auth-dsn.js +143 -0
  13. package/dist/application/doctor/auth-dsn.js.map +1 -0
  14. package/dist/application/doctor/auth-flow.js +28 -0
  15. package/dist/application/doctor/auth-flow.js.map +1 -0
  16. package/dist/application/doctor/auth-registry.js +12 -0
  17. package/dist/application/doctor/auth-registry.js.map +1 -0
  18. package/dist/application/doctor/hosts.js +41 -0
  19. package/dist/application/doctor/hosts.js.map +1 -0
  20. package/dist/application/doctor/native-host-state.js +211 -0
  21. package/dist/application/doctor/native-host-state.js.map +1 -0
  22. package/dist/application/doctor/prepare.js +262 -0
  23. package/dist/application/doctor/prepare.js.map +1 -0
  24. package/dist/application/doctor/provider-installation.js +124 -0
  25. package/dist/application/doctor/provider-installation.js.map +1 -0
  26. package/dist/application/doctor/provider-mcps.js +650 -0
  27. package/dist/application/doctor/provider-mcps.js.map +1 -0
  28. package/dist/application/doctor/provider-plugins-hooks.js +112 -0
  29. package/dist/application/doctor/provider-plugins-hooks.js.map +1 -0
  30. package/dist/application/doctor/provider-skills.js +212 -0
  31. package/dist/application/doctor/provider-skills.js.map +1 -0
  32. package/dist/application/doctor/provider-tools-auth.js +201 -0
  33. package/dist/application/doctor/provider-tools-auth.js.map +1 -0
  34. package/dist/application/doctor/provider-visibility.js +149 -0
  35. package/dist/application/doctor/provider-visibility.js.map +1 -0
  36. package/dist/application/doctor/repair-runner.js +169 -0
  37. package/dist/application/doctor/repair-runner.js.map +1 -0
  38. package/dist/application/doctor/report.js +155 -0
  39. package/dist/application/doctor/report.js.map +1 -0
  40. package/dist/application/doctor/types.js +5 -0
  41. package/dist/application/doctor/types.js.map +1 -0
  42. package/dist/application/flow/advance.js +152 -13
  43. package/dist/application/flow/advance.js.map +1 -1
  44. package/dist/application/flow/flow-service.js +18 -7
  45. package/dist/application/flow/flow-service.js.map +1 -1
  46. package/dist/application/flow/internal-actions.js +167 -7
  47. package/dist/application/flow/internal-actions.js.map +1 -1
  48. package/dist/application/flow/run-projection.js +6 -1
  49. package/dist/application/flow/run-projection.js.map +1 -1
  50. package/dist/application/flow/submit.js +330 -7
  51. package/dist/application/flow/submit.js.map +1 -1
  52. package/dist/application/mcp-doctor-service.js +1 -1
  53. package/dist/application/mcp-doctor-service.js.map +1 -1
  54. package/dist/application/mcp-host-reader.js +134 -26
  55. package/dist/application/mcp-host-reader.js.map +1 -1
  56. package/dist/application/mcp-host-receipt-service.js +9 -7
  57. package/dist/application/mcp-host-receipt-service.js.map +1 -1
  58. package/dist/application/plan-current-point.js +54 -0
  59. package/dist/application/plan-current-point.js.map +1 -0
  60. package/dist/application/plan-exec-decision-service.js +143 -4
  61. package/dist/application/plan-exec-decision-service.js.map +1 -1
  62. package/dist/application/plan-locator.js +78 -0
  63. package/dist/application/plan-locator.js.map +1 -0
  64. package/dist/application/plan-open-run.js +129 -0
  65. package/dist/application/plan-open-run.js.map +1 -0
  66. package/dist/application/reseal-service.js +14 -44
  67. package/dist/application/reseal-service.js.map +1 -1
  68. package/dist/application/resume-service.js +9 -3
  69. package/dist/application/resume-service.js.map +1 -1
  70. package/dist/application/self/install-skill.js +10 -2
  71. package/dist/application/self/install-skill.js.map +1 -1
  72. package/dist/application/self/mcp-config.js +1 -1
  73. package/dist/application/self/mcp-config.js.map +1 -1
  74. package/dist/application/session-narrative.js +15 -0
  75. package/dist/application/session-narrative.js.map +1 -1
  76. package/dist/application/settle-service.js +442 -0
  77. package/dist/application/settle-service.js.map +1 -0
  78. package/dist/application/source-boundary-policy.js +87 -6
  79. package/dist/application/source-boundary-policy.js.map +1 -1
  80. package/dist/application/workline-index-service.js +165 -62
  81. package/dist/application/workline-index-service.js.map +1 -1
  82. package/dist/cli/commands/amend.js +122 -0
  83. package/dist/cli/commands/amend.js.map +1 -0
  84. package/dist/cli/commands/doctor.js +300 -0
  85. package/dist/cli/commands/doctor.js.map +1 -0
  86. package/dist/cli/commands/index.js +6 -0
  87. package/dist/cli/commands/index.js.map +1 -1
  88. package/dist/cli/commands/settle.js +197 -0
  89. package/dist/cli/commands/settle.js.map +1 -0
  90. package/dist/cli/commands/status.js +2 -0
  91. package/dist/cli/commands/status.js.map +1 -1
  92. package/dist/cli/dispatch-plan.js +47 -0
  93. package/dist/cli/dispatch-plan.js.map +1 -0
  94. package/dist/cli/help-groups.js +15 -0
  95. package/dist/cli/help-groups.js.map +1 -1
  96. package/dist/cli/main.js +54 -10
  97. package/dist/cli/main.js.map +1 -1
  98. package/dist/cli/parser.js +26 -0
  99. package/dist/cli/parser.js.map +1 -1
  100. package/dist/domain/decision-note.js +166 -3
  101. package/dist/domain/decision-note.js.map +1 -1
  102. package/dist/domain/decision-preview.js.map +1 -1
  103. package/dist/domain/doctor/auth.js +65 -0
  104. package/dist/domain/doctor/auth.js.map +1 -0
  105. package/dist/domain/doctor/model.js +82 -0
  106. package/dist/domain/doctor/model.js.map +1 -0
  107. package/dist/domain/doctor/operations.js +114 -0
  108. package/dist/domain/doctor/operations.js.map +1 -0
  109. package/dist/domain/effective-contract.js +4 -3
  110. package/dist/domain/effective-contract.js.map +1 -1
  111. package/dist/domain/flow/answer.js +10 -0
  112. package/dist/domain/flow/answer.js.map +1 -1
  113. package/dist/domain/flow/authority.js +124 -0
  114. package/dist/domain/flow/authority.js.map +1 -1
  115. package/dist/domain/flow/directive.js +8 -1
  116. package/dist/domain/flow/directive.js.map +1 -1
  117. package/dist/domain/flow/run-state.js +276 -34
  118. package/dist/domain/flow/run-state.js.map +1 -1
  119. package/dist/domain/obligation-correspondence.js +95 -0
  120. package/dist/domain/obligation-correspondence.js.map +1 -0
  121. package/dist/domain/reconciliation.js +142 -25
  122. package/dist/domain/reconciliation.js.map +1 -1
  123. package/dist/domain/redaction.js +40 -0
  124. package/dist/domain/redaction.js.map +1 -1
  125. package/dist/domain/settlement.js +129 -0
  126. package/dist/domain/settlement.js.map +1 -0
  127. package/package.json +1 -1
  128. package/skills/w/SKILL.md +2 -1
  129. package/skills/w/commands/README.md +2 -1
  130. package/skills/w/commands/doctor.md +31 -0
  131. package/skills/w/commands/resume.md +2 -2
  132. package/skills/w/context/MANIFEST.json +4 -0
  133. package/skills/w/loops/plan-exec-loop/LOOP.md +31 -0
@@ -0,0 +1,149 @@
1
+ import { doctorFindingId } from "../../domain/doctor/model.js";
2
+ /**
3
+ * Workspace visibility — the declared sources against the ones each host has
4
+ * registered.
5
+ *
6
+ * One finding per drift CLASS that is actually present, driven by the `missing`
7
+ * and `extra` lists rather than by the aggregate status: a report whose status
8
+ * is `missing-paths` may also carry extras, and a single finding per host would
9
+ * hide one of the two.
10
+ *
11
+ * With no project block in the current directory there is nothing to compare,
12
+ * and that is `not-applicable` — not a warning. Someone running the doctor from
13
+ * a directory that is not a workspace has not misconfigured anything.
14
+ */
15
+ import { harnessForMcpHost } from "../../domain/harnesses.js";
16
+ import { runVisibilityDoctor } from "../visibility-doctor-service.js";
17
+ import { coverage } from "./types.js";
18
+ const CATEGORY = "workspace-visibility";
19
+ /**
20
+ * The visibility engine speaks `McpHost` ids and the report speaks catalog ids.
21
+ *
22
+ * They differ for exactly one host — `claude` against `claude-code` — and that
23
+ * one difference is enough to make a report list the same machine twice under
24
+ * two names. Translated at the boundary, once.
25
+ */
26
+ function catalogHost(host) {
27
+ return harnessForMcpHost(host)?.id ?? host;
28
+ }
29
+ export const visibilityProvider = {
30
+ category: CATEGORY,
31
+ async run(input) {
32
+ const result = await runVisibilityDoctor(input.ctx.fs, input.ctx.env, input.ctx.paths, {
33
+ workspace: input.workspaceDir,
34
+ global: true,
35
+ });
36
+ const reports = [...result.reports, ...result.global_reports];
37
+ const findings = [];
38
+ const coverages = [];
39
+ // The visibility engine always inspects its own hardcoded set of hosts; the
40
+ // run's selection is the aggregator's answer, and it is the one that counts.
41
+ // `selectDoctorHosts` already split the participants from the hosts with no
42
+ // trace here and applied `--only`. Without this filter the report enumerated
43
+ // a host as absent and, two sections below, declared it `comprobada ✔` with
44
+ // a healthy finding — and `--only kimi` still diagnosed claude-code, codex
45
+ // and warp.
46
+ const participants = new Set(input.hosts.map((host) => host.host));
47
+ for (const report of reports) {
48
+ const host = catalogHost(report.host);
49
+ if (!participants.has(host))
50
+ continue;
51
+ if (report.status === "no-project-block") {
52
+ coverages.push(coverage(CATEGORY, host, "not-applicable", `no hay bloque de proyecto para ${report.host} en ${input.workspaceDir}`));
53
+ continue;
54
+ }
55
+ coverages.push(coverage(CATEGORY, host, "checked"));
56
+ findings.push(...driftFindings(report));
57
+ }
58
+ // Y el complemento: un host participante que este motor NO sabe mirar
59
+ // declara `not-applicable`, no silencio. El motor sólo inspecciona
60
+ // claude/codex/warp; filtrar sin decirlo dejaba una máquina cuyo único host
61
+ // es gemini con CERO filas de esta categoría, y el agregador leía ese
62
+ // silencio como «no se pudo comprobar» y sacaba el doctor en 1 sobre un
63
+ // entorno sano. No mirar por diseño y no haber podido mirar son dos estados
64
+ // distintos, y sólo el segundo escala.
65
+ const covered = new Set(coverages.map((entry) => entry.host));
66
+ const uncovered = input.hosts
67
+ .filter((host) => !covered.has(host.host))
68
+ .map((host) => coverage(CATEGORY, host.host, "not-applicable", `la visibilidad multiroot no se declara para ${host.label}: sólo Claude Code, Codex y Warp registran rutas del workspace`));
69
+ return { coverage: [...dedupe(coverages), ...uncovered], findings };
70
+ },
71
+ };
72
+ function driftFindings(report) {
73
+ const resource = `${report.scope}:visibilidad`;
74
+ const host = catalogHost(report.host);
75
+ const base = {
76
+ host,
77
+ category: CATEGORY,
78
+ resource: {
79
+ kind: "visibility",
80
+ name: `${host} (${report.scope})`,
81
+ locator: report.target,
82
+ },
83
+ ownership: "ours",
84
+ };
85
+ const findings = [];
86
+ if (report.missing.length > 0) {
87
+ findings.push({
88
+ ...base,
89
+ id: doctorFindingId(host, CATEGORY, `${resource}:faltantes`),
90
+ state: "warning",
91
+ summary: `${host} no tiene registradas ${report.missing.length} ruta(s) declarada(s)`,
92
+ impact: "el host no ve esas fuentes: sus lecturas y ediciones ahí fallan",
93
+ evidence: report.missing.map((path) => `falta: ${path}`),
94
+ remediation: { kind: "manual", action: null, guidance: ["aw attach-multiroot"] },
95
+ proposal: { op: "multiroot.attach", args: { scope: report.scope } },
96
+ });
97
+ }
98
+ if (report.extra.length > 0) {
99
+ findings.push({
100
+ ...base,
101
+ id: doctorFindingId(host, CATEGORY, `${resource}:sobrantes`),
102
+ state: "warning",
103
+ summary: `${host} tiene registradas ${report.extra.length} ruta(s) que nadie declaró`,
104
+ impact: "el host ve directorios fuera del workspace declarado",
105
+ evidence: report.extra.map((path) => `sobra: ${path}`),
106
+ remediation: { kind: "manual", action: null, guidance: ["aw detach-multiroot"] },
107
+ proposal: { op: "multiroot.detach", args: { scope: report.scope } },
108
+ });
109
+ }
110
+ if (report.status === "no-settings") {
111
+ findings.push({
112
+ ...base,
113
+ id: doctorFindingId(host, CATEGORY, `${resource}:sin-config`),
114
+ state: "warning",
115
+ summary: `${host} no tiene el archivo de configuración que declara sus rutas`,
116
+ impact: "el host no ve ninguna fuente declarada del workspace",
117
+ evidence: [`archivo esperado: ${report.target}`],
118
+ remediation: { kind: "manual", action: null, guidance: ["aw attach-multiroot"] },
119
+ proposal: { op: "multiroot.attach", args: { scope: report.scope } },
120
+ });
121
+ }
122
+ if (findings.length === 0) {
123
+ findings.push({
124
+ ...base,
125
+ id: doctorFindingId(host, CATEGORY, resource),
126
+ state: "healthy",
127
+ summary: `${host} tiene registradas exactamente las rutas declaradas (${report.scope})`,
128
+ impact: "el host ve el workspace completo y nada más",
129
+ evidence: [
130
+ `archivo: ${report.target}`,
131
+ `rutas registradas: ${report.registered_paths.length}`,
132
+ ],
133
+ remediation: { kind: "none", action: null, guidance: [] },
134
+ });
135
+ }
136
+ return findings;
137
+ }
138
+ // A host inspected in both scopes reports its coverage twice; the report keeps
139
+ // one row per category and host.
140
+ function dedupe(entries) {
141
+ const byHost = new Map();
142
+ for (const entry of entries) {
143
+ const held = byHost.get(entry.host);
144
+ if (held === undefined || held.state === "not-applicable")
145
+ byHost.set(entry.host, entry);
146
+ }
147
+ return [...byHost.values()];
148
+ }
149
+ //# sourceMappingURL=provider-visibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-visibility.js","sourceRoot":"","sources":["../../../src/application/doctor/provider-visibility.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,169 @@
1
+ import { readMcpConnections } from "../mcp-connections-service.js";
2
+ import { runMcpMigration } from "../mcp-migration-service.js";
3
+ import { runMcpRemove } from "../mcp-remove-service.js";
4
+ import { runMcpSetup } from "../mcp-setup-service.js";
5
+ import { runMultiroot } from "../multiroot-service.js";
6
+ import { selfCleanLegacy } from "../self/clean-legacy.js";
7
+ import { selfInstallHooks } from "../self/install-hooks.js";
8
+ import { selfInstallSkill } from "../self/install-skill.js";
9
+ import { reinstallSkill } from "../self/skills-manager.js";
10
+ import { selfUninstall } from "../self/uninstall.js";
11
+ import { runDoctorAuthFlow } from "./auth-flow.js";
12
+ /** Un `ParsedArgs` explícito: sin comando, sin positional y con los flags que la operación pide. */
13
+ function argsOf(values, flags = []) {
14
+ return {
15
+ rest: [],
16
+ plugin: {},
17
+ flags: new Set(flags),
18
+ values: new Map(Object.entries(values)),
19
+ valuesMulti: new Map(),
20
+ };
21
+ }
22
+ /** Un `CommandResult` se traduce por su `ok` y su `exitCode`, nunca por su prosa. */
23
+ function fromCommand(result, what) {
24
+ if (result.ok)
25
+ return { status: "applied", detail: `${what}: aplicado` };
26
+ const code = result.error?.code ?? "sin código";
27
+ // `blocked` es el estado que `install-hooks` usa cuando una entrada inválida
28
+ // de la persona desarmaría la sección: no es un fallo del doctor, es una
29
+ // negativa deliberada de la operación, y se respeta como tal.
30
+ const blocked = code === "HOOKS_BLOCKED" || code.endsWith("_BLOCKED");
31
+ return {
32
+ status: blocked ? "blocked" : "failed",
33
+ detail: `${what}: ${code}`,
34
+ };
35
+ }
36
+ export async function runDoctorRepair(action, ctx) {
37
+ switch (action.op) {
38
+ case "self.install-skill":
39
+ return fromCommand(await selfInstallSkill(argsOf({ target: target(action) }), ctx), "instalar el bundle");
40
+ case "self.uninstall":
41
+ return fromCommand(await selfUninstall(argsOf({ target: target(action) }), ctx), "retirar la configuración residual");
42
+ case "self.install-hooks":
43
+ return fromCommand(await selfInstallHooks(argsOf({ target: target(action) }), ctx), "armar los hooks");
44
+ case "self.clean-legacy":
45
+ return fromCommand(await selfCleanLegacy(argsOf({ target: target(action) }), ctx), "limpiar el resto legacy");
46
+ case "skills.reinstall":
47
+ return fromCommand(await reinstallSkill(ctx, action.args.name ?? ""), "reinstalar la skill");
48
+ case "mcp.setup":
49
+ return mcpOutcome(runMcpSetup(ctx.env, mcpInput(ctx, action)), "registrar la entrada MCP");
50
+ case "mcp.remove":
51
+ return mcpOutcome(runMcpRemove(ctx.env, mcpInput(ctx, action)), "retirar la entrada MCP");
52
+ case "mcp.migrate":
53
+ return migrateOutcome(action, ctx);
54
+ case "auth.flow":
55
+ return runDoctorAuthFlow(action, ctx);
56
+ case "multiroot.attach":
57
+ case "multiroot.detach":
58
+ return multirootOutcome(await runMultiroot(ctx.fs, ctx.env, ctx.paths, action.op === "multiroot.attach" ? "attach" : "detach", {
59
+ fromSources: true,
60
+ useGlobal: action.args.scope === "global",
61
+ }));
62
+ default:
63
+ // Una operación que el catálogo declara y este adaptador no sabe correr es
64
+ // un fallo declarado, no un `applied` optimista: el recurso queda como
65
+ // estaba y la recomprobación lo va a confirmar.
66
+ return { status: "failed", detail: `no hay adaptador para la operación '${action.op}'` };
67
+ }
68
+ }
69
+ function target(action) {
70
+ return (action.args.target ?? "");
71
+ }
72
+ /**
73
+ * El scope global exige su propia autorización, y acá la hay.
74
+ *
75
+ * `globalApproval: "explicit-self-action"` es exactamente lo que este caso es:
76
+ * una persona leyó la vista previa de este lote y aprobó su digest. Sin ese
77
+ * valor `runMcpSetup` se niega a escribir una configuración global, y con razón
78
+ * — tocarla afecta todos los proyectos de la máquina.
79
+ */
80
+ function mcpInput(ctx, action) {
81
+ const host = (action.args.host ?? "");
82
+ const instance = action.args.instance ?? "";
83
+ const connections = readMcpConnections(ctx.paths, ctx.env).filter((connection) => connection.name === instance);
84
+ const scope = action.args.scope === "global" ? "global" : "workspace";
85
+ return {
86
+ hosts: [host],
87
+ connections,
88
+ ...(scope === "global"
89
+ ? { scope: "global", globalApproval: "explicit-self-action" }
90
+ : { scope: "workspace", workspace: ctx.paths.workspaceDir() }),
91
+ };
92
+ }
93
+ /**
94
+ * Los servicios de MCP no lanzan: acumulan y devuelven parcial.
95
+ *
96
+ * Así que el resultado se lee de sus listas, no de una excepción. Un conflicto
97
+ * es una entrada ajena homónima que el servicio PRESERVÓ, y eso no es un fallo
98
+ * del doctor sino la protección funcionando: se reporta como fallo de la acción
99
+ * porque el recurso no quedó reparado, con la razón a la vista.
100
+ */
101
+ function mcpOutcome(result, what) {
102
+ if ("error" in result)
103
+ return { status: "failed", detail: `${what}: ${result.error}` };
104
+ const conflicts = result.conflicts?.length ?? 0;
105
+ const errors = result.errors?.length ?? 0;
106
+ if (conflicts > 0) {
107
+ return {
108
+ status: "blocked",
109
+ detail: `${what}: hay una entrada homónima ajena y se preservó`,
110
+ };
111
+ }
112
+ if (errors > 0)
113
+ return { status: "failed", detail: `${what}: ${errors} error(es) del host` };
114
+ const applied = result.applied?.length ?? 0;
115
+ return applied > 0
116
+ ? { status: "applied", detail: `${what}: aplicado` }
117
+ : { status: "failed", detail: `${what}: el servicio no escribió nada` };
118
+ }
119
+ /**
120
+ * La migración habla otro idioma: sus pasos son `items` con su propia acción.
121
+ *
122
+ * Y su `apply` es explícito — sin él la corrida es una vista previa. El doctor
123
+ * ya trae la aprobación del digest, así que acá aplica; el `globalApproval` de
124
+ * este servicio es un booleano y no la etiqueta que usa `setup`, otro caso donde
125
+ * dos servicios hermanos no comparten firma y el adaptador es el único lugar que
126
+ * lo sabe.
127
+ */
128
+ function migrateOutcome(action, ctx) {
129
+ const host = (action.args.host ?? "");
130
+ const instance = action.args.instance ?? "";
131
+ const connections = readMcpConnections(ctx.paths, ctx.env).filter((connection) => connection.name === instance);
132
+ const result = action.args.scope === "global"
133
+ ? runMcpMigration(ctx.env, {
134
+ scope: "global",
135
+ hosts: [host],
136
+ connections,
137
+ apply: true,
138
+ globalApproval: true,
139
+ })
140
+ : runMcpMigration(ctx.env, {
141
+ scope: "workspace",
142
+ workspace: ctx.paths.workspaceDir(),
143
+ hosts: [host],
144
+ connections,
145
+ apply: true,
146
+ });
147
+ if ("error" in result)
148
+ return { status: "failed", detail: `migrar: ${String(result.error)}` };
149
+ const blocked = result.items.filter((item) => item.action === "blocked");
150
+ if (blocked.length > 0) {
151
+ return { status: "blocked", detail: "migrar: el servicio declaró el paso bloqueado" };
152
+ }
153
+ const failed = result.items.filter((item) => item.action === "failed");
154
+ if (failed.length > 0)
155
+ return { status: "failed", detail: "migrar: el servicio reportó un fallo" };
156
+ const moved = result.items.filter((item) => item.action === "install" || item.action === "replace-known-legacy");
157
+ return moved.length > 0
158
+ ? { status: "applied", detail: "migrar: aplicado" }
159
+ : { status: "failed", detail: "migrar: no había nada que mover" };
160
+ }
161
+ function multirootOutcome(result) {
162
+ const error = result !== null && typeof result === "object" && "error" in result
163
+ ? String(result.error)
164
+ : null;
165
+ return error === null
166
+ ? { status: "applied", detail: "visibilidad multiroot: aplicada" }
167
+ : { status: "failed", detail: `visibilidad multiroot: ${error}` };
168
+ }
169
+ //# sourceMappingURL=repair-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-runner.js","sourceRoot":"","sources":["../../../src/application/doctor/repair-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * The aggregate: run every provider, consolidate, redact, and let the verdict
3
+ * fall out of what was found.
4
+ *
5
+ * A provider that throws does not take the report down with it. Its category
6
+ * becomes `unavailable` WITH THE REASON on every participating host, and the
7
+ * verdict turns non-zero — because a doctor that answers 0 after failing to look
8
+ * is read as "healthy", which is the one thing it must never say by accident.
9
+ */
10
+ import { DOCTOR_SCHEMA_VERSION, doctorFindingId, doctorVerdict, sortDoctorCoverage, sortDoctorFindings, summarizeDoctorFindings, } from "../../domain/doctor/model.js";
11
+ import { redactSensitiveValue } from "../../domain/redaction.js";
12
+ import { readPackageVersion } from "../../runtime/version.js";
13
+ import { annotateRepairs } from "./actions.js";
14
+ import { DOCTOR_HOST_ORDER, selectDoctorHosts } from "./hosts.js";
15
+ import { installationProvider } from "./provider-installation.js";
16
+ import { createMcpsProvider } from "./provider-mcps.js";
17
+ import { pluginsHooksProvider } from "./provider-plugins-hooks.js";
18
+ import { skillsProvider } from "./provider-skills.js";
19
+ import { toolsAuthProvider } from "./provider-tools-auth.js";
20
+ import { visibilityProvider } from "./provider-visibility.js";
21
+ import { coverage } from "./types.js";
22
+ export function defaultDoctorProviders(deps = {}) {
23
+ return [
24
+ installationProvider,
25
+ createMcpsProvider(deps),
26
+ skillsProvider,
27
+ toolsAuthProvider,
28
+ pluginsHooksProvider,
29
+ visibilityProvider,
30
+ ];
31
+ }
32
+ export async function runDoctor(ctx, options = {}, deps = {}) {
33
+ const currentHost = normalizeHost(options.host ?? null);
34
+ const only = [...(options.only ?? [])];
35
+ const selection = await selectDoctorHosts(ctx, { currentHost, only });
36
+ const workspaceDir = ctx.paths.workspaceDir();
37
+ const input = {
38
+ ctx,
39
+ hosts: selection.hosts,
40
+ hostStates: selection.states,
41
+ currentHost,
42
+ workspaceDir,
43
+ skipNative: options.skipNative === true,
44
+ ...(options.verify === undefined ? {} : { verifyAuthorization: options.verify }),
45
+ };
46
+ // Un `--only` mal escrito se denuncia ANTES de mirar nada: es lo único que
47
+ // explica por qué la corrida no cubrió lo que la persona creía haber pedido.
48
+ const findings = selection.unknownOnly.map(unknownOnlyFinding);
49
+ const coverages = [];
50
+ for (const provider of deps.providers ?? defaultDoctorProviders(deps.mcps)) {
51
+ try {
52
+ const output = await provider.run(input);
53
+ findings.push(...output.findings);
54
+ // Silencio NO es cobertura: una categoría que desaparece del informe deja
55
+ // a `doctorVerdict` sin nada que ver y el doctor sale 0 después de no
56
+ // haber mirado (AC-02, AC-14). Pero el estado del relleno es
57
+ // `not-applicable`, NO `unavailable`: un proveedor calla cuando la corrida
58
+ // no le dio ningún host que le corresponda —una máquina sin ningún host de
59
+ // agente, o un `--only` que no dejó participantes—, y eso es «no había
60
+ // nada que comprobar», no «no se pudo comprobar». Marcarlo caído ponía en
61
+ // rojo un entorno sano; lo que sí escala es el proveedor que LANZA, abajo,
62
+ // y un `--only` que nombra lo que el catálogo no declara, que ya viaja
63
+ // como hallazgo bloqueante.
64
+ coverages.push(...(output.coverage.length > 0
65
+ ? output.coverage
66
+ : [coverage(provider.category, "workspace", "not-applicable", silenceReason(selection))]));
67
+ }
68
+ catch (error) {
69
+ const reason = `el proveedor falló: ${messageOf(error)}`;
70
+ const scopes = selection.hosts.length > 0 ? selection.hosts.map((h) => h.host) : ["workspace"];
71
+ for (const host of scopes) {
72
+ coverages.push(coverage(provider.category, host, "unavailable", reason));
73
+ }
74
+ }
75
+ }
76
+ const hostOrder = [...DOCTOR_HOST_ORDER, "workspace"];
77
+ // El gate de propiedad, en un solo lugar y sobre el conjunto consolidado: acá
78
+ // es donde una sugerencia de proveedor se vuelve acción, o no. También es
79
+ // donde `proposal` se consume: el informe emitido no la lleva.
80
+ const orderedFindings = sortDoctorFindings(annotateRepairs(findings), hostOrder);
81
+ const orderedCoverage = sortDoctorCoverage(coverages, hostOrder);
82
+ const report = {
83
+ schema_version: DOCTOR_SCHEMA_VERSION,
84
+ cli_version: readPackageVersion(),
85
+ scope: { workspace_dir: workspaceDir, current_host: currentHost, only },
86
+ hosts: selection.hosts.map(({ mcp_host: _mcpHost, ...view }) => view),
87
+ hosts_absent: selection.absent,
88
+ coverage: orderedCoverage,
89
+ findings: orderedFindings,
90
+ summary: summarizeDoctorFindings(orderedFindings),
91
+ verdict: doctorVerdict(orderedFindings, orderedCoverage),
92
+ };
93
+ // Last line of defence, over the WHOLE object and once: the same redaction the
94
+ // CLI already applies to every command's output. A provider that reads a file
95
+ // holding a credential cannot leak it past here.
96
+ return redactSensitiveValue(report);
97
+ }
98
+ /**
99
+ * Por qué una categoría no declaró ni una fila de cobertura.
100
+ *
101
+ * Las tres razones son distintas y la persona necesita la suya: un filtro que
102
+ * no existe, una selección sin hosts, o un proveedor que miró y no dijo nada.
103
+ */
104
+ function silenceReason(selection) {
105
+ if (selection.unknownOnly.length > 0) {
106
+ return `no había nada que comprobar: --only nombra hosts que el catálogo no declara (${selection.unknownOnly.join(", ")})`;
107
+ }
108
+ if (selection.hosts.length === 0) {
109
+ return "no había nada que comprobar: ningún host participa en esta corrida";
110
+ }
111
+ return "el proveedor no declaró cobertura para ningún host de la corrida";
112
+ }
113
+ /**
114
+ * El hallazgo de un `--only` que el catálogo no conoce.
115
+ *
116
+ * Bloqueante a propósito: la corrida NO miró el host que se pidió, y un cero
117
+ * ahí se lee como «tu entorno está sano». La sugerencia sale del catálogo, así
118
+ * que `--only claude` apunta a `claude-code` sin que este módulo cablee ningún
119
+ * alias propio.
120
+ */
121
+ function unknownOnlyFinding(name) {
122
+ const near = DOCTOR_HOST_ORDER.filter((id) => id.includes(name) || name.includes(id));
123
+ const evidence = [`el catálogo declara: ${DOCTOR_HOST_ORDER.join(", ")}`];
124
+ if (near.length > 0)
125
+ evidence.push(`el nombre más parecido del catálogo: ${near.join(", ")}`);
126
+ return {
127
+ id: doctorFindingId("workspace", "installation-hosts", `--only=${name}`),
128
+ host: "workspace",
129
+ category: "installation-hosts",
130
+ resource: { kind: "filtro", name: `--only=${name}`, locator: null },
131
+ state: "blocking",
132
+ summary: `--only nombra «${name}», que el catálogo de hosts no declara`,
133
+ impact: "el diagnóstico no cubrió el host que pediste y no puede hablar por él",
134
+ evidence,
135
+ ownership: "n/a",
136
+ remediation: {
137
+ kind: "manual",
138
+ action: null,
139
+ guidance: [
140
+ near.length > 0
141
+ ? `repetí la corrida con --only ${near[0]}`
142
+ : "repetí la corrida con un id del catálogo, o sin --only para mirar todos los hosts",
143
+ ],
144
+ },
145
+ };
146
+ }
147
+ function normalizeHost(host) {
148
+ if (host === null)
149
+ return null;
150
+ return DOCTOR_HOST_ORDER.includes(host) ? host : null;
151
+ }
152
+ function messageOf(error) {
153
+ return error instanceof Error ? error.message : String(error);
154
+ }
155
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/application/doctor/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** `checked` carries no reason; everything else must say why. */
2
+ export function coverage(category, host, state, reason = null) {
3
+ return { category, host, state, reason };
4
+ }
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/application/doctor/types.ts"],"names":[],"mappings":"AAgEA,iEAAiE;AACjE,MAAM,UAAU,QAAQ,CACtB,QAAwB,EACxB,IAAY,EACZ,KAA8B,EAC9B,SAAwB,IAAI;IAE5B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC3C,CAAC"}