@nac3/forge-cli 1.23.4 → 1.23.5
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.
- package/dist/chat/doctrine_digest.d.ts.map +1 -1
- package/dist/chat/doctrine_digest.js +4 -1
- package/dist/chat/doctrine_digest.js.map +1 -1
- package/dist/chat/tools/evidence.d.ts +34 -2
- package/dist/chat/tools/evidence.d.ts.map +1 -1
- package/dist/chat/tools/evidence.js +90 -12
- package/dist/chat/tools/evidence.js.map +1 -1
- package/dist/commands/urazuke.d.ts.map +1 -1
- package/dist/commands/urazuke.js +27 -0
- package/dist/commands/urazuke.js.map +1 -1
- package/dist/core/error_catalog.d.ts +4 -0
- package/dist/core/error_catalog.d.ts.map +1 -1
- package/dist/core/error_catalog.js +16 -0
- package/dist/core/error_catalog.js.map +1 -1
- package/dist/core/loopback_post.d.ts +101 -0
- package/dist/core/loopback_post.d.ts.map +1 -0
- package/dist/core/loopback_post.js +156 -0
- package/dist/core/loopback_post.js.map +1 -0
- package/dist/docs/doctrine/urazuke.md +50 -38
- package/dist/mcp/forge_panel_server.d.ts +1 -26
- package/dist/mcp/forge_panel_server.d.ts.map +1 -1
- package/dist/mcp/forge_panel_server.js +5 -26
- package/dist/mcp/forge_panel_server.js.map +1 -1
- package/dist/mcp/forge_verbs_server.d.ts +1 -11
- package/dist/mcp/forge_verbs_server.d.ts.map +1 -1
- package/dist/mcp/forge_verbs_server.js +7 -23
- package/dist/mcp/forge_verbs_server.js.map +1 -1
- package/dist/mcp/panel_invoke.d.ts +51 -0
- package/dist/mcp/panel_invoke.d.ts.map +1 -0
- package/dist/mcp/panel_invoke.js +102 -0
- package/dist/mcp/panel_invoke.js.map +1 -0
- package/dist/nac3/internal_manifest.d.ts +2 -0
- package/dist/nac3/internal_manifest.d.ts.map +1 -1
- package/dist/nac3/internal_manifest.js +18 -3
- package/dist/nac3/internal_manifest.js.map +1 -1
- package/dist/nac3/verb_budget.d.ts +110 -0
- package/dist/nac3/verb_budget.d.ts.map +1 -0
- package/dist/nac3/verb_budget.js +142 -0
- package/dist/nac3/verb_budget.js.map +1 -0
- package/dist/relay/loopback_turn.d.ts +15 -42
- package/dist/relay/loopback_turn.d.ts.map +1 -1
- package/dist/relay/loopback_turn.js +27 -115
- package/dist/relay/loopback_turn.js.map +1 -1
- package/dist/urazuke/evidence.d.ts +22 -0
- package/dist/urazuke/evidence.d.ts.map +1 -1
- package/dist/urazuke/evidence.js +42 -3
- package/dist/urazuke/evidence.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/doctrine/urazuke.md +50 -38
- package/package.json +1 -1
- package/src/i18n/catalogs/ar.json +3 -0
- package/src/i18n/catalogs/de.json +3 -0
- package/src/i18n/catalogs/en.json +3 -0
- package/src/i18n/catalogs/es.json +3 -0
- package/src/i18n/catalogs/fr.json +3 -0
- package/src/i18n/catalogs/hi.json +3 -0
- package/src/i18n/catalogs/it.json +3 -0
- package/src/i18n/catalogs/ja.json +3 -0
- package/src/i18n/catalogs/pt.json +3 -0
- package/src/i18n/catalogs/zh.json +3 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El canal por el que un server MCP le pide a Forge que ejecute un verbo.
|
|
3
|
+
*
|
|
4
|
+
* Los dos servers MCP (forge_panel y forge_verbs) son NIETOS de Forge: Forge
|
|
5
|
+
* lanza `claude -p` y `claude -p` los lanza a ellos. No comparten memoria con
|
|
6
|
+
* el servidor de chat, asi que cada invocacion viaja por HTTP al loopback
|
|
7
|
+
* (POST /api/forge/panel-invoke), donde corre el dispatcher real.
|
|
8
|
+
*
|
|
9
|
+
* POR QUE EL REENVIO VIVE ACA Y NO EN CADA SERVER (PND-235). Estaba duplicado
|
|
10
|
+
* -- dos copias de la misma funcion, una en cada server -- y las dos heredaban
|
|
11
|
+
* el mismo techo de cinco minutos de undici. Un techo duplicado se arregla dos
|
|
12
|
+
* veces o, peor, una sola: el otro sigue roto y nadie se da cuenta hasta que
|
|
13
|
+
* el usuario lo pisa. Es la misma leccion que el export web y su dependencia
|
|
14
|
+
* del workspace (PND-239), el mismo dia.
|
|
15
|
+
*
|
|
16
|
+
* El presupuesto de la espera sale de lo que el VERBO declara
|
|
17
|
+
* (nac3/verb_budget.ts) y el transporte es el compartido con el camino del
|
|
18
|
+
* telefono (core/loopback_post.ts).
|
|
19
|
+
*
|
|
20
|
+
* ASCII puro.
|
|
21
|
+
*/
|
|
22
|
+
import { type LoopbackResponse } from '../core/loopback_post.js';
|
|
23
|
+
/** Puerto + token del servidor de chat, que Forge le pasa al server MCP por
|
|
24
|
+
* env al generar el mcp-config. El token gatea el endpoint para que ningun
|
|
25
|
+
* otro proceso local pueda inyectar invocaciones. */
|
|
26
|
+
export interface PanelChannel {
|
|
27
|
+
port?: string | undefined;
|
|
28
|
+
token?: string | undefined;
|
|
29
|
+
}
|
|
30
|
+
/** El transporte, inyectable para test. Misma forma que postLoopbackJson. */
|
|
31
|
+
export type LoopbackPost = (args: {
|
|
32
|
+
port: number;
|
|
33
|
+
path: string;
|
|
34
|
+
payload: unknown;
|
|
35
|
+
budgetMs: number;
|
|
36
|
+
}) => Promise<LoopbackResponse>;
|
|
37
|
+
export declare const PANEL_INVOKE_PATH = "/api/forge/panel-invoke";
|
|
38
|
+
export declare function panelChannelFromEnv(env?: NodeJS.ProcessEnv): PanelChannel;
|
|
39
|
+
/**
|
|
40
|
+
* Reenvia una invocacion al chat server (dispatcher real) y devuelve el texto
|
|
41
|
+
* del resultado.
|
|
42
|
+
*
|
|
43
|
+
* Nunca lanza: el llamador es un handler JSON-RPC y lo unico que puede hacer
|
|
44
|
+
* con una excepcion es convertirla en texto, asi que se convierte aca una sola
|
|
45
|
+
* vez y bien.
|
|
46
|
+
*/
|
|
47
|
+
export declare function forwardInvoke(verbId: string, args: Record<string, unknown>, env?: PanelChannel, post?: LoopbackPost): Promise<{
|
|
48
|
+
ok: boolean;
|
|
49
|
+
text: string;
|
|
50
|
+
}>;
|
|
51
|
+
//# sourceMappingURL=panel_invoke.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel_invoke.d.ts","sourceRoot":"","sources":["../../src/mcp/panel_invoke.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAiC,KAAK,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAKhG;;sDAEsD;AACtD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE;IAChC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CAChE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAEhC,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;AAE3D,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,YAAY,CAEtF;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,GAAG,GAAE,YAAoC,EACzC,IAAI,GAAE,YAA+B,GACpC,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA6DxC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* El canal por el que un server MCP le pide a Forge que ejecute un verbo.
|
|
3
|
+
*
|
|
4
|
+
* Los dos servers MCP (forge_panel y forge_verbs) son NIETOS de Forge: Forge
|
|
5
|
+
* lanza `claude -p` y `claude -p` los lanza a ellos. No comparten memoria con
|
|
6
|
+
* el servidor de chat, asi que cada invocacion viaja por HTTP al loopback
|
|
7
|
+
* (POST /api/forge/panel-invoke), donde corre el dispatcher real.
|
|
8
|
+
*
|
|
9
|
+
* POR QUE EL REENVIO VIVE ACA Y NO EN CADA SERVER (PND-235). Estaba duplicado
|
|
10
|
+
* -- dos copias de la misma funcion, una en cada server -- y las dos heredaban
|
|
11
|
+
* el mismo techo de cinco minutos de undici. Un techo duplicado se arregla dos
|
|
12
|
+
* veces o, peor, una sola: el otro sigue roto y nadie se da cuenta hasta que
|
|
13
|
+
* el usuario lo pisa. Es la misma leccion que el export web y su dependencia
|
|
14
|
+
* del workspace (PND-239), el mismo dia.
|
|
15
|
+
*
|
|
16
|
+
* El presupuesto de la espera sale de lo que el VERBO declara
|
|
17
|
+
* (nac3/verb_budget.ts) y el transporte es el compartido con el camino del
|
|
18
|
+
* telefono (core/loopback_post.ts).
|
|
19
|
+
*
|
|
20
|
+
* ASCII puro.
|
|
21
|
+
*/
|
|
22
|
+
import { postLoopbackJson, LoopbackCut } from '../core/loopback_post.js';
|
|
23
|
+
import { renderForgeError, E_VERB_CALL_UNANSWERED } from '../core/error_catalog.js';
|
|
24
|
+
import { formatForgeErrorText } from '../core/error_formatter.js';
|
|
25
|
+
import { invokeBudgetMs } from '../nac3/verb_budget.js';
|
|
26
|
+
export const PANEL_INVOKE_PATH = '/api/forge/panel-invoke';
|
|
27
|
+
export function panelChannelFromEnv(env = process.env) {
|
|
28
|
+
return { port: env['FORGE_PANEL_PORT'], token: env['FORGE_PANEL_TOKEN'] };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reenvia una invocacion al chat server (dispatcher real) y devuelve el texto
|
|
32
|
+
* del resultado.
|
|
33
|
+
*
|
|
34
|
+
* Nunca lanza: el llamador es un handler JSON-RPC y lo unico que puede hacer
|
|
35
|
+
* con una excepcion es convertirla en texto, asi que se convierte aca una sola
|
|
36
|
+
* vez y bien.
|
|
37
|
+
*/
|
|
38
|
+
export async function forwardInvoke(verbId, args, env = panelChannelFromEnv(), post = postLoopbackJson) {
|
|
39
|
+
if (!env.port || !env.token) {
|
|
40
|
+
return { ok: false, text: 'El canal de Forge no esta configurado (sin puerto/token).' };
|
|
41
|
+
}
|
|
42
|
+
/* Un puerto que no es un numero es una MALA CONFIGURACION, y hay que decirlo
|
|
43
|
+
* asi. Sin esta guarda, `http.request({port: NaN})` tira y el error cae en
|
|
44
|
+
* el catch de abajo, que lo reporta como "la invocacion no contesto" -- o
|
|
45
|
+
* sea: el unico caso en que se sabe con certeza que el verbo no corrio se
|
|
46
|
+
* reportaria como el caso en que pudo haber corrido. */
|
|
47
|
+
const port = Number(env.port);
|
|
48
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
text: 'El canal de Forge esta mal configurado: FORGE_PANEL_PORT no es un puerto ('
|
|
52
|
+
+ JSON.stringify(env.port) + '). El verbo NO se ejecuto.',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const budgetMs = invokeBudgetMs(verbId, args);
|
|
56
|
+
let r;
|
|
57
|
+
try {
|
|
58
|
+
r = await post({
|
|
59
|
+
port,
|
|
60
|
+
path: PANEL_INVOKE_PATH,
|
|
61
|
+
payload: { token: env.token, verb_id: verbId, args },
|
|
62
|
+
budgetMs,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (err instanceof LoopbackCut && err.kind === 'undelivered') {
|
|
67
|
+
/* Prueba positiva de que no corrio nada: el saludo TCP no existio. Es el
|
|
68
|
+
* unico caso en que se puede afirmar que el verbo no se ejecuto. */
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
text: 'El canal de Forge no respondio: no hay nadie escuchando en el puerto '
|
|
72
|
+
+ env.port + '. El verbo NO se ejecuto.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/* En cualquier otro corte el verbo pudo haber corrido, asi que no se dice
|
|
76
|
+
* que fracaso: se dice que no hubo respuesta y donde mirar el rastro. */
|
|
77
|
+
const minutes = Math.max(1, Math.round(budgetMs / 60_000));
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
text: formatForgeErrorText(renderForgeError(E_VERB_CALL_UNANSWERED, { verb: verbId, minutes })),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (r.status < 200 || r.status >= 300) {
|
|
84
|
+
return { ok: false, text: 'Forge rechazo la invocacion (HTTP ' + r.status + ').' };
|
|
85
|
+
}
|
|
86
|
+
let j;
|
|
87
|
+
try {
|
|
88
|
+
j = JSON.parse(r.body);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
/* 200 con un cuerpo que no es JSON: no es "no contesto", es que contesto
|
|
92
|
+
* otra cosa. Decirlo con lo que llego adentro, que es el unico dato que
|
|
93
|
+
* permite diagnosticarlo. */
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
text: 'Forge contesto algo que no es JSON (HTTP ' + r.status + '): '
|
|
97
|
+
+ r.body.slice(0, 300),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return { ok: j.ok !== false, text: j.text || 'Listo.' };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=panel_invoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel_invoke.js","sourceRoot":"","sources":["../../src/mcp/panel_invoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal_manifest.d.ts","sourceRoot":"","sources":["../../src/nac3/internal_manifest.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,UAAU,GAClB,cAAc,GACd,SAAS,GACT,mBAAmB,GACnB,aAAa,GACb,eAAe,GACf,oBAAoB,CAAC;AAEzB,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,KAAK,GACL,YAAY,GACZ,SAAS,GACT,SAAS,GACT,cAAc,GACd,KAAK,CAAC;AAEV,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;QAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"internal_manifest.d.ts","sourceRoot":"","sources":["../../src/nac3/internal_manifest.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,UAAU,GAClB,cAAc,GACd,SAAS,GACT,mBAAmB,GACnB,aAAa,GACb,eAAe,GACf,oBAAoB,CAAC;AAEzB,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,KAAK,GACL,YAAY,GACZ,SAAS,GACT,SAAS,GACT,cAAc,GACd,KAAK,CAAC;AAEV,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;QAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QAKnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB;;;4BAGwB;IACxB,YAAY,EAAE,OAAO,GAAG,QAAQ,CAAC;IACjC;;;;;;qCAMiC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAm7GD,wBAAgB,QAAQ,IAAI,YAAY,CAOvC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAGzD;AAED;gEACgE;AAChE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAO9D;AAED;;;uDAGuD;AACvD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CA2CzF;AAED;;sEAEsE;AACtE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,MAAM,EAAE,CAO/D"}
|
|
@@ -1260,7 +1260,7 @@ const VERBS = [
|
|
|
1260
1260
|
properties: {
|
|
1261
1261
|
command: { type: 'string', description: 'The shell command to run.', minLength: 1, maxLength: 16384 },
|
|
1262
1262
|
cwd: { type: 'string', description: 'Working directory. Absolute or project-relative. Outside-root requires extra approval (limits.shell.cwd_boundary_strict).' },
|
|
1263
|
-
timeout_ms: { type: 'number', description: 'Override timeout. Capped by limits.shell.timeout_ms_max.' },
|
|
1263
|
+
timeout_ms: { type: 'number', maximum: 600000, description: 'Override timeout. Capped by limits.shell.timeout_ms_max (whose own hard ceiling is 600000). The transport budget is derived from this maximum: see nac3/verb_budget.ts.' },
|
|
1264
1264
|
env: { type: 'object', description: 'Extra env vars to inject on top of the whitelist.' },
|
|
1265
1265
|
allow_long_running: { type: 'boolean', description: 'Escape hatch: run a non-terminating command in-turn anyway (rare). Default false -> use yujin.task.run instead.' },
|
|
1266
1266
|
allow_heavy: { type: 'boolean', description: 'Escape hatch for the HEAVY guard (test suites, builds, installs, sleeps): run it in-turn anyway. Default false -> yujin.task.run + yujin.task.log({grep}) instead, which does not block the turn.' },
|
|
@@ -2871,7 +2871,10 @@ const VERBS = [
|
|
|
2871
2871
|
+ 'regression, e2e, quality, mutation, load, other. Receipts are what '
|
|
2872
2872
|
+ 'the method accepts as evidence: a plan pending closes with shipped '
|
|
2873
2873
|
+ 'only with its red_proof + green + regression receipts. Blocks the '
|
|
2874
|
-
+ 'turn
|
|
2874
|
+
+ 'turn while the run fits the blocking window (10 min); over that, or '
|
|
2875
|
+
+ 'with background:true, it is launched DETACHED and you get a handle -- '
|
|
2876
|
+
+ 'the receipt lands either way, read it with yujin.evidence.list. '
|
|
2877
|
+
+ 'Never describe a run you did not record here.',
|
|
2875
2878
|
schema: {
|
|
2876
2879
|
type: 'object',
|
|
2877
2880
|
properties: {
|
|
@@ -2881,7 +2884,8 @@ const VERBS = [
|
|
|
2881
2884
|
step: { type: 'number', description: 'Urazuke step number, when the run is for a ladder step.' },
|
|
2882
2885
|
base_ref: { type: 'string', maxLength: 100, description: 'red_proof: the git ref of the code BEFORE the change. Default HEAD (the uncommitted change is what is being proved).' },
|
|
2883
2886
|
test_files: { type: 'array', description: 'red_proof: the new test files, project-relative, carried into the base worktree.' },
|
|
2884
|
-
timeout_ms: { type: 'number', description: 'Max 1800000.' },
|
|
2887
|
+
timeout_ms: { type: 'number', maximum: 1800000, description: 'Max 1800000 (30 min). Over the blocking window (10 min) the run goes to the BACKGROUND and the verb returns a handle instead of the receipt.' },
|
|
2888
|
+
background: { type: 'boolean', description: 'Launch the run DETACHED and return a handle instead of blocking the turn. Automatic when timeout_ms is over the blocking window. The receipt is written by the run itself: read it with yujin.evidence.list when it finishes.' },
|
|
2885
2889
|
note: { type: 'string', maxLength: 300 },
|
|
2886
2890
|
},
|
|
2887
2891
|
required: ['kind', 'command'],
|
|
@@ -3385,6 +3389,17 @@ export function validateArgs(verb, args) {
|
|
|
3385
3389
|
return 'arg ' + key + ': expected array, got ' + actual;
|
|
3386
3390
|
if (expected !== 'array' && actual !== expected)
|
|
3387
3391
|
return 'arg ' + key + ': expected ' + expected + ', got ' + actual;
|
|
3392
|
+
if (expected === 'number' && typeof val === 'number') {
|
|
3393
|
+
/* Un tope declarado que nadie hace valer es prosa. Y se RECHAZA en vez
|
|
3394
|
+
* de recortar en silencio: el que pide 30 minutos donde entran 10 tiene
|
|
3395
|
+
* que enterarse, no recibir otra cosa de la que pidio. */
|
|
3396
|
+
if (propSchema.minimum != null && val < propSchema.minimum) {
|
|
3397
|
+
return 'arg ' + key + ': too small (min ' + propSchema.minimum + ')';
|
|
3398
|
+
}
|
|
3399
|
+
if (propSchema.maximum != null && val > propSchema.maximum) {
|
|
3400
|
+
return 'arg ' + key + ': too big (max ' + propSchema.maximum + ')';
|
|
3401
|
+
}
|
|
3402
|
+
}
|
|
3388
3403
|
if (expected === 'string' && typeof val === 'string') {
|
|
3389
3404
|
if (propSchema.minLength != null && val.length < propSchema.minLength) {
|
|
3390
3405
|
return 'arg ' + key + ': too short (min ' + propSchema.minLength + ')';
|