nexgenk 1.4.1 → 1.6.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.
- package/dist/main.mjs +1723 -999
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -47481,6 +47481,14 @@ var init_session$4 = __esmMin((() => {
|
|
|
47481
47481
|
enabled: false
|
|
47482
47482
|
});
|
|
47483
47483
|
}
|
|
47484
|
+
async setWaveMode(enabled) {
|
|
47485
|
+
this.ensureOpen();
|
|
47486
|
+
if (typeof enabled !== "boolean") throw new NexgenError(ErrorCodes$1.REQUEST_INVALID, "Session wave mode must be a boolean");
|
|
47487
|
+
await this.rpc.setWaveMode({
|
|
47488
|
+
sessionId: this.id,
|
|
47489
|
+
enabled
|
|
47490
|
+
});
|
|
47491
|
+
}
|
|
47484
47492
|
async setTowerMode(enabled, base) {
|
|
47485
47493
|
this.ensureOpen();
|
|
47486
47494
|
if (typeof enabled !== "boolean") throw new NexgenError(ErrorCodes$1.REQUEST_INVALID, "Session tower mode must be a boolean");
|
|
@@ -106094,6 +106102,12 @@ var init_statusReader = __esmMin((() => {
|
|
|
106094
106102
|
INBOX_COUNT_LIMIT = 1e3;
|
|
106095
106103
|
RECENT_LOG_LINES = 10;
|
|
106096
106104
|
}));
|
|
106105
|
+
// ../../packages/agent-core-v2/src/features/wave/agent/waveMode.ts
|
|
106106
|
+
var IAgentWaveService;
|
|
106107
|
+
var init_waveMode = __esmMin((() => {
|
|
106108
|
+
init_instantiation();
|
|
106109
|
+
IAgentWaveService = createDecorator("agentWaveService");
|
|
106110
|
+
}));
|
|
106097
106111
|
// ../../packages/agent-core-v2/src/_base/di/descriptors.ts
|
|
106098
106112
|
var SyncDescriptor;
|
|
106099
106113
|
var init_descriptors = __esmMin((() => {
|
|
@@ -111222,7 +111236,7 @@ function dump$1(input, options) {
|
|
|
111222
111236
|
if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
|
|
111223
111237
|
return "";
|
|
111224
111238
|
}
|
|
111225
|
-
var common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type$2, schema, str$3, seq, map, failsafe, _null, bool
|
|
111239
|
+
var common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type$2, schema, str$3, seq, map, failsafe, _null, bool, int, YAML_FLOAT_PATTERN, SCIENTIFIC_WITHOUT_DOT, float, json, core, YAML_DATE_REGEXP, YAML_TIMESTAMP_REGEXP, timestamp$1, merge, BASE64_MAP, binary, _hasOwnProperty$3, _toString$2, omap, _toString$1, pairs, _hasOwnProperty$2, set$1, _default, _hasOwnProperty$1, CONTEXT_FLOW_IN, CONTEXT_FLOW_OUT, CONTEXT_BLOCK_IN, CONTEXT_BLOCK_OUT, CHOMPING_CLIP, CHOMPING_STRIP, CHOMPING_KEEP, PATTERN_NON_PRINTABLE, PATTERN_NON_ASCII_LINE_BREAKS, PATTERN_FLOW_INDICATORS, PATTERN_TAG_HANDLE, PATTERN_TAG_URI, simpleEscapeCheck, simpleEscapeMap, i$1, directiveHandlers, loader, _toString, _hasOwnProperty, CHAR_BOM, CHAR_TAB, CHAR_LINE_FEED, CHAR_CARRIAGE_RETURN, CHAR_SPACE, CHAR_EXCLAMATION, CHAR_DOUBLE_QUOTE, CHAR_SHARP, CHAR_PERCENT, CHAR_AMPERSAND, CHAR_SINGLE_QUOTE, CHAR_ASTERISK, CHAR_COMMA, CHAR_MINUS, CHAR_COLON, CHAR_EQUALS, CHAR_GREATER_THAN, CHAR_QUESTION, CHAR_COMMERCIAL_AT, CHAR_LEFT_SQUARE_BRACKET, CHAR_RIGHT_SQUARE_BRACKET, CHAR_GRAVE_ACCENT, CHAR_LEFT_CURLY_BRACKET, CHAR_VERTICAL_LINE, CHAR_RIGHT_CURLY_BRACKET, ESCAPE_SEQUENCES, DEPRECATED_BOOLEANS_SYNTAX, DEPRECATED_BASE60_SYNTAX, QUOTING_TYPE_SINGLE, QUOTING_TYPE_DOUBLE, STYLE_PLAIN, STYLE_SINGLE, STYLE_LITERAL, STYLE_FOLDED, STYLE_DOUBLE, dumper, load;
|
|
111226
111240
|
var init_js_yaml = __esmMin((() => {
|
|
111227
111241
|
common = {
|
|
111228
111242
|
isNothing,
|
|
@@ -111330,7 +111344,7 @@ var init_js_yaml = __esmMin((() => {
|
|
|
111330
111344
|
},
|
|
111331
111345
|
defaultStyle: "lowercase"
|
|
111332
111346
|
});
|
|
111333
|
-
bool
|
|
111347
|
+
bool = new type$2("tag:yaml.org,2002:bool", {
|
|
111334
111348
|
kind: "scalar",
|
|
111335
111349
|
resolve: resolveYamlBoolean,
|
|
111336
111350
|
construct: constructYamlBoolean,
|
|
@@ -111387,7 +111401,7 @@ var init_js_yaml = __esmMin((() => {
|
|
|
111387
111401
|
});
|
|
111388
111402
|
json = failsafe.extend({ implicit: [
|
|
111389
111403
|
_null,
|
|
111390
|
-
bool
|
|
111404
|
+
bool,
|
|
111391
111405
|
int,
|
|
111392
111406
|
float
|
|
111393
111407
|
] });
|
|
@@ -125575,17 +125589,18 @@ var init_update_config = __esmMin((() => {
|
|
|
125575
125589
|
};
|
|
125576
125590
|
}));
|
|
125577
125591
|
// ../../packages/agent-core-v2/src/features/wave/wave.ts
|
|
125578
|
-
var WAVE_FLAG_ID
|
|
125592
|
+
var WAVE_FLAG_ID, WAVE_FLAG_ENV, WAVE_SEAT_PROFILE, WAVE_DIRECTOR_PROFILE, WAVE_TOOL_DOMAIN;
|
|
125579
125593
|
var init_wave$3 = __esmMin((() => {
|
|
125580
|
-
WAVE_FLAG_ID
|
|
125594
|
+
WAVE_FLAG_ID = "wave";
|
|
125581
125595
|
WAVE_FLAG_ENV = "NEXGEN_EXPERIMENTAL_WAVE";
|
|
125582
125596
|
WAVE_SEAT_PROFILE = "wave-seat";
|
|
125597
|
+
WAVE_DIRECTOR_PROFILE = "agent";
|
|
125583
125598
|
WAVE_TOOL_DOMAIN = "wave";
|
|
125584
125599
|
}));
|
|
125585
125600
|
// ../../packages/agent-core-v2/src/features/skill/catalog/builtin/wave.md?raw
|
|
125586
125601
|
var wave_default;
|
|
125587
125602
|
var init_wave$2 = __esmMin((() => {
|
|
125588
|
-
wave_default = "---\nname: wave\ndescription: Run one design wave end to end
|
|
125603
|
+
wave_default = "---\nname: wave\ndescription: Run one design wave end to end as its director — open the wave, contract one agent per seat, then decide, verify and close on the gate. Use when the user enables wave mode and gives an objective for a backlog built with adversarial review instead of a single agent's opinion.\ndisableModelInvocation: true\n---\n\n# Wave (director → asientos → gate)\n\nEl agente principal es el **director**: abre la oleada, contrata asientos y comprueba resultados. **No escribe artefactos.** Cada artefacto lo entrega un asiento `wave-seat` con `WaveSubmit`, que es la única tool que hereda el rol, la ruta y el ticket de su contrato.\n\nUn asiento ve `Read`, `Glob`, `Grep` y `WaveSubmit` — nada más. No tiene gate, ni quórum, ni puede lanzar agentes: si necesita un dato que no tiene, escribe UNKNOWN y lo nombra.\n\n## Qué hace falta antes de empezar\n\n- `workflow.config.json` en la raíz (layout, umbrales, vocabulario, quórum, roles).\n- Un brief real: **siete secciones**, alcance con claves contables, evidencia disponible y rúbrica.\n\nSi falta el config, no hay oleada: pide al usuario que lo cree desde la plantilla. Si el brief tiene menos de siete secciones, `WaveContract` se niega — no lo rodees escribiendo el brief tú.\n\n## El ciclo\n\n1. `WaveOpen({ name })` crea `design/waves/W<n>-<slug>/` con el esqueleto del brief y declara la oleada en el config.\n2. Rellena el brief. Las preguntas de diseño van ahí, no en el prompt de un asiento.\n3. `WaveContract({ wave, round: \"propose\" })` devuelve un contrato por asiento: rol, ruta, ticket y prompt. **Lanza un agente `wave-seat` por contrato** con `Agent` (o `AgentSwarm` si el usuario activó swarm), pasando el prompt tal cual. No lo reescribas: el ticket del prompt es lo que `WaveSubmit` acepta.\n4. `round: \"defend\"` y `round: \"attack\"` en la misma tanda.\n5. `round: \"judge\"`: cada juez devuelve su tabla y su total por propuesta.\n6. `WaveDecide({ wave, verdicts })` con los totales de los jueces: `adopt`, `refine` o `deadlock`. Sin `adopt`, contrata `refine` (R1) y después `audit` (R2).\n7. Aplica los parches de R2 y recompón el backlog (`consolidate` → `backlog`) por script, nunca a mano.\n8. `WaveGate({ wave })`: si sale en rojo, la oleada no está cerrada, por mucho que la prosa diga que sí.\n9. Ejecución: una task por vez; antes de cerrarla, `WaveVerify({ task })` con su `verify` y su mutante.\n\n`WaveContract({ wave, round, report: true })` lista qué asientos ya entregaron y cuáles faltan, sin emitir tickets: úsalo para decidir si relanzas o cierras.\n\n## Reglas que no se negocian\n\n- **Un asiento, un artefacto, un contrato.** El contrato fija rol y ruta; `WaveSubmit` los exige. Un asiento no escribe el artefacto de otro ni toca el backlog, y el director no escribe ninguno.\n- **Aislamiento en la ronda 1.** Un proponente no ve las propuestas de los otros. Si se ven, no son tres propuestas: es una con tres firmas.\n- **Los ataques no puntúan.** Un adversario que dice cuál es mejor está gastando su asiento; su producto son hallazgos con id y una mutación que los demuestra.\n- **Ningún hallazgo entra como párrafo.** Entra como override, task nueva o retirada, aplicado por script. Un defecto que acaba en el acta y no en el backlog no está corregido: está decorado.\n- **Quórum por mediana y por juez.** Un empate en la mediana no corona a nadie. Dos rondas sin quórum se cierran adoptando R1 **con disidencia escrita**, nunca presentándolo como unánime.\n\n## Qué no decir a un asiento\n\nNo le cuentes qué dicen las otras propuestas, no le pidas consenso, no le des el número de hallazgos esperado y no le adelantes qué propuesta quieres que gane. Cualquiera de las cuatro convierte el swarm en teatro.\n\n## Cuándo parar\n\n- Brief que depende de evidencia que no existe: declara `UNKNOWN` con dueño, o trocea la oleada. No se rellena con invención plausible.\n- Gate rojo por causa externa: regístralo como bloqueo con nombre y sigue con lo que no depende de ella. Nunca marques en verde lo que no se ejecutó.\n";
|
|
125589
125604
|
}));
|
|
125590
125605
|
// ../../packages/agent-core-v2/src/features/skill/catalog/builtin/wave.ts
|
|
125591
125606
|
var PSEUDO_PATH$1, parsed$1, WAVE_SKILL;
|
|
@@ -125604,7 +125619,7 @@ var init_wave$1 = __esmMin((() => {
|
|
|
125604
125619
|
...parsed$1,
|
|
125605
125620
|
path: PSEUDO_PATH$1,
|
|
125606
125621
|
dir: PSEUDO_PATH$1,
|
|
125607
|
-
experimentalFlag: WAVE_FLAG_ID
|
|
125622
|
+
experimentalFlag: WAVE_FLAG_ID,
|
|
125608
125623
|
metadata: {
|
|
125609
125624
|
...parsed$1.metadata,
|
|
125610
125625
|
type: parsed$1.metadata.type ?? "inline"
|
|
@@ -192175,7 +192190,7 @@ var init_host_request_headers = __esmMin((() => {
|
|
|
192175
192190
|
}));
|
|
192176
192191
|
// ../../packages/agent-core-v2/src/human/llm/requester/bases/anthropic/contract.ts
|
|
192177
192192
|
var CONTEXT_MANAGEMENT_BETA;
|
|
192178
|
-
var init_contract$
|
|
192193
|
+
var init_contract$5 = __esmMin((() => {
|
|
192179
192194
|
CONTEXT_MANAGEMENT_BETA = "context-management-2025-06-27";
|
|
192180
192195
|
}));
|
|
192181
192196
|
// ../../packages/agent-core-v2/src/human/llm/syntax-errors.ts
|
|
@@ -192598,7 +192613,7 @@ function nexgenkUnsetCompletionTokens(input) {
|
|
|
192598
192613
|
var NEXGEN_API_KEY_ENV, NEXGEN_BASE_URL_ENV$1, NEXGEN_DEFAULT_BASE_URL, nexgenkEndpoint$1, nexgenkConnection, nexgenkAcceptedImageMimes, nexgenkResponsesTrait, nexgenkOpenAITrait, nexgenkAnthropicTrait;
|
|
192599
192614
|
var init_trait = __esmMin((() => {
|
|
192600
192615
|
init_image_formats();
|
|
192601
|
-
init_contract$
|
|
192616
|
+
init_contract$5();
|
|
192602
192617
|
init_schema$3();
|
|
192603
192618
|
NEXGEN_API_KEY_ENV = "NEXGEN_API_KEY";
|
|
192604
192619
|
NEXGEN_BASE_URL_ENV$1 = "NEXGEN_BASE_URL";
|
|
@@ -196108,7 +196123,7 @@ var init_format$4 = __esmMin((() => {
|
|
|
196108
196123
|
init_syntax_errors();
|
|
196109
196124
|
init_patterns$3();
|
|
196110
196125
|
init_rewrite();
|
|
196111
|
-
init_contract$
|
|
196126
|
+
init_contract$5();
|
|
196112
196127
|
init_lower$3();
|
|
196113
196128
|
init_patterns$2();
|
|
196114
196129
|
init_profile();
|
|
@@ -219258,6 +219273,90 @@ var init_towerService = __esmMin((() => {
|
|
|
219258
219273
|
], AgentTowerService);
|
|
219259
219274
|
registerScopedService("agent", IAgentTowerService, AgentTowerService, 0, "tower");
|
|
219260
219275
|
}));
|
|
219276
|
+
// ../../packages/agent-core-v2/src/features/wave/waveOps.ts
|
|
219277
|
+
var waveModeEnterSchema, WaveModeEnter, waveModeExitSchema, WaveModeExit, waveKey;
|
|
219278
|
+
var init_waveOps = __esmMin((() => {
|
|
219279
|
+
init_zod$1();
|
|
219280
|
+
init_usageEvents();
|
|
219281
|
+
init_event2();
|
|
219282
|
+
init_state$1();
|
|
219283
|
+
waveModeEnterSchema = object$1({ agentId: string() });
|
|
219284
|
+
WaveModeEnter = class extends AgentEvent2 {
|
|
219285
|
+
static type = "wave_mode.enter";
|
|
219286
|
+
static durable = true;
|
|
219287
|
+
static schema = waveModeEnterSchema;
|
|
219288
|
+
};
|
|
219289
|
+
waveModeExitSchema = object$1({ agentId: string() });
|
|
219290
|
+
WaveModeExit = class extends AgentEvent2 {
|
|
219291
|
+
static type = "wave_mode.exit";
|
|
219292
|
+
static durable = true;
|
|
219293
|
+
static schema = waveModeExitSchema;
|
|
219294
|
+
};
|
|
219295
|
+
waveKey = defineState("wave", () => false).replayable({ schema: boolean$1() }).on(WaveModeEnter, (_s, e, ctx) => {
|
|
219296
|
+
ctx.emit(new AgentStatusUpdated({
|
|
219297
|
+
agentId: e.agentId,
|
|
219298
|
+
waveMode: true
|
|
219299
|
+
}));
|
|
219300
|
+
return true;
|
|
219301
|
+
}).on(WaveModeExit, (_s, e, ctx) => {
|
|
219302
|
+
ctx.emit(new AgentStatusUpdated({
|
|
219303
|
+
agentId: e.agentId,
|
|
219304
|
+
waveMode: false
|
|
219305
|
+
}));
|
|
219306
|
+
return false;
|
|
219307
|
+
});
|
|
219308
|
+
}));
|
|
219309
|
+
// ../../packages/agent-core-v2/src/features/wave/agent/waveService.ts
|
|
219310
|
+
var AgentWaveService;
|
|
219311
|
+
var init_waveService = __esmMin((() => {
|
|
219312
|
+
init_lifecycle$2();
|
|
219313
|
+
init_profile$1();
|
|
219314
|
+
init_scopeContext();
|
|
219315
|
+
init_agentState();
|
|
219316
|
+
init_eventBus();
|
|
219317
|
+
init_agentLifecycle();
|
|
219318
|
+
init_eventDispatcher();
|
|
219319
|
+
init_waveOps();
|
|
219320
|
+
init_decorateParam();
|
|
219321
|
+
init_decorate();
|
|
219322
|
+
AgentWaveService = class AgentWaveService extends Disposable {
|
|
219323
|
+
dispatcher;
|
|
219324
|
+
agentCtx;
|
|
219325
|
+
agentState;
|
|
219326
|
+
profile;
|
|
219327
|
+
constructor(dispatcher, agentCtx, agentState, profile, eventBus) {
|
|
219328
|
+
super();
|
|
219329
|
+
this.dispatcher = dispatcher;
|
|
219330
|
+
this.agentCtx = agentCtx;
|
|
219331
|
+
this.agentState = agentState;
|
|
219332
|
+
this.profile = profile;
|
|
219333
|
+
this.agentState.contributeState(waveKey);
|
|
219334
|
+
const republish = () => {
|
|
219335
|
+
if (this.agentCtx.agentId === "main") this.profile.republishStatus();
|
|
219336
|
+
};
|
|
219337
|
+
this._register(eventBus.subscribe(WaveModeEnter, republish));
|
|
219338
|
+
this._register(eventBus.subscribe(WaveModeExit, republish));
|
|
219339
|
+
}
|
|
219340
|
+
async enter() {
|
|
219341
|
+
if (this.agentState.get(waveKey)) return;
|
|
219342
|
+
await this.dispatcher.dispatch(new WaveModeEnter({ agentId: this.agentCtx.agentId }));
|
|
219343
|
+
}
|
|
219344
|
+
async exit() {
|
|
219345
|
+
if (!this.agentState.get(waveKey)) return;
|
|
219346
|
+
await this.dispatcher.dispatch(new WaveModeExit({ agentId: this.agentCtx.agentId }));
|
|
219347
|
+
}
|
|
219348
|
+
get isActive() {
|
|
219349
|
+
return this.agentState.get(waveKey);
|
|
219350
|
+
}
|
|
219351
|
+
};
|
|
219352
|
+
AgentWaveService = __decorate([
|
|
219353
|
+
__decorateParam(0, IEventDispatcher),
|
|
219354
|
+
__decorateParam(1, IAgentScopeContext),
|
|
219355
|
+
__decorateParam(2, IAgentStateService),
|
|
219356
|
+
__decorateParam(3, IAgentProfileService),
|
|
219357
|
+
__decorateParam(4, IEventBus)
|
|
219358
|
+
], AgentWaveService);
|
|
219359
|
+
}));
|
|
219261
219360
|
// ../../packages/agent-core-v2/src/features/wave/seatProfile.ts
|
|
219262
219361
|
var WAVE_SEAT_TOOLS, WAVE_SEAT_ROLE, WAVE_SEAT_PROFILE_DEF;
|
|
219263
219362
|
var init_seatProfile = __esmMin((() => {
|
|
@@ -219279,217 +219378,67 @@ var init_seatProfile = __esmMin((() => {
|
|
|
219279
219378
|
renderSystemPrompt: (context) => renderSystemPromptResult(WAVE_SEAT_ROLE, context, { skillActive: skillActiveFor(WAVE_SEAT_TOOLS) })
|
|
219280
219379
|
});
|
|
219281
219380
|
}));
|
|
219282
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/
|
|
219283
|
-
var
|
|
219284
|
-
var
|
|
219381
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/contract/contract.ts
|
|
219382
|
+
var WAVE_CONTRACT_ROUNDS, WaveContractToolInputSchema, IWaveContractTool;
|
|
219383
|
+
var init_contract$4 = __esmMin((() => {
|
|
219285
219384
|
init_zod$1();
|
|
219286
219385
|
init_instantiation();
|
|
219287
|
-
|
|
219288
|
-
|
|
219289
|
-
|
|
219290
|
-
|
|
219291
|
-
|
|
219292
|
-
|
|
219293
|
-
|
|
219294
|
-
|
|
219295
|
-
|
|
219386
|
+
WAVE_CONTRACT_ROUNDS = [
|
|
219387
|
+
"propose",
|
|
219388
|
+
"defend",
|
|
219389
|
+
"attack",
|
|
219390
|
+
"judge",
|
|
219391
|
+
"refine",
|
|
219392
|
+
"audit"
|
|
219393
|
+
];
|
|
219394
|
+
WaveContractToolInputSchema = object$1({
|
|
219395
|
+
wave: string().min(2),
|
|
219396
|
+
round: _enum(WAVE_CONTRACT_ROUNDS),
|
|
219397
|
+
seats: array(object$1({
|
|
219398
|
+
role: string().min(1).optional(),
|
|
219399
|
+
artifact: string().min(1).optional()
|
|
219400
|
+
}).strict()).optional(),
|
|
219401
|
+
report: boolean$1().optional(),
|
|
219402
|
+
root: string().optional()
|
|
219296
219403
|
}).strict();
|
|
219297
|
-
|
|
219404
|
+
IWaveContractTool = createDecorator("waveContractTool");
|
|
219298
219405
|
}));
|
|
219299
|
-
// ../../packages/agent-core-v2/src/features/wave/core/
|
|
219300
|
-
function
|
|
219301
|
-
|
|
219406
|
+
// ../../packages/agent-core-v2/src/features/wave/core/fsJson.ts
|
|
219407
|
+
function readJson$2(fs, path) {
|
|
219408
|
+
const text = fs.read(path);
|
|
219409
|
+
if (text === void 0) return void 0;
|
|
219410
|
+
try {
|
|
219411
|
+
return JSON.parse(text);
|
|
219412
|
+
} catch {
|
|
219413
|
+
return;
|
|
219414
|
+
}
|
|
219302
219415
|
}
|
|
219303
|
-
function
|
|
219304
|
-
return typeof value === "
|
|
219416
|
+
function isRecord$16(value) {
|
|
219417
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
219305
219418
|
}
|
|
219306
|
-
function
|
|
219307
|
-
return
|
|
219419
|
+
function asRecord$2(value) {
|
|
219420
|
+
return isRecord$16(value) ? value : {};
|
|
219308
219421
|
}
|
|
219309
|
-
function
|
|
219310
|
-
return
|
|
219422
|
+
function asArray$2(value) {
|
|
219423
|
+
return Array.isArray(value) ? value : [];
|
|
219311
219424
|
}
|
|
219312
|
-
function
|
|
219313
|
-
return
|
|
219425
|
+
function asText$1(value) {
|
|
219426
|
+
return typeof value === "string" ? value : "";
|
|
219314
219427
|
}
|
|
219315
|
-
function
|
|
219316
|
-
|
|
219317
|
-
|
|
219318
|
-
const thresholds = record$2(base["thresholds"]);
|
|
219319
|
-
const vocabulary = record$2(base["vocabulary"]);
|
|
219320
|
-
const roles = record$2(base["roles"]);
|
|
219321
|
-
const quorum = record$2(base["quorum"]);
|
|
219322
|
-
return {
|
|
219323
|
-
layout: {
|
|
219324
|
-
waves: text(layout["waves"], DEFAULT_LAYOUT.waves),
|
|
219325
|
-
backlog: text(layout["backlog"], DEFAULT_LAYOUT.backlog),
|
|
219326
|
-
adr: text(layout["adr"], DEFAULT_LAYOUT.adr),
|
|
219327
|
-
inventory: text(layout["inventory"], DEFAULT_LAYOUT.inventory)
|
|
219328
|
-
},
|
|
219329
|
-
waves: strArray$1(base["waves"], ["W0"]),
|
|
219330
|
-
thresholds: {
|
|
219331
|
-
minEpics: num(thresholds["minEpics"], DEFAULT_THRESHOLDS.minEpics),
|
|
219332
|
-
minTasks: num(thresholds["minTasks"], DEFAULT_THRESHOLDS.minTasks),
|
|
219333
|
-
minAcPerTask: num(thresholds["minAcPerTask"], DEFAULT_THRESHOLDS.minAcPerTask),
|
|
219334
|
-
minDecisionBytes: num(thresholds["minDecisionBytes"], DEFAULT_THRESHOLDS.minDecisionBytes),
|
|
219335
|
-
minArtifactBytes: num(thresholds["minArtifactBytes"], DEFAULT_THRESHOLDS.minArtifactBytes),
|
|
219336
|
-
minBriefSections: num(thresholds["minBriefSections"], DEFAULT_THRESHOLDS.minBriefSections),
|
|
219337
|
-
minContextBytes: num(thresholds["minContextBytes"], DEFAULT_THRESHOLDS.minContextBytes),
|
|
219338
|
-
minGoalChars: num(thresholds["minGoalChars"], DEFAULT_THRESHOLDS.minGoalChars),
|
|
219339
|
-
minScopeChars: num(thresholds["minScopeChars"], DEFAULT_THRESHOLDS.minScopeChars),
|
|
219340
|
-
minFieldChars: num(thresholds["minFieldChars"], DEFAULT_THRESHOLDS.minFieldChars),
|
|
219341
|
-
minMetricChars: num(thresholds["minMetricChars"], DEFAULT_THRESHOLDS.minMetricChars),
|
|
219342
|
-
allowVerifyTargetMissing: bool(thresholds["allowVerifyTargetMissing"], DEFAULT_THRESHOLDS.allowVerifyTargetMissing)
|
|
219343
|
-
},
|
|
219344
|
-
vocabulary: {
|
|
219345
|
-
areas: strArray$1(vocabulary["areas"], DEFAULT_VOCABULARY.areas),
|
|
219346
|
-
requiredAreas: strArray$1(vocabulary["requiredAreas"], DEFAULT_VOCABULARY.requiredAreas),
|
|
219347
|
-
types: strArray$1(vocabulary["types"], DEFAULT_VOCABULARY.types),
|
|
219348
|
-
estimates: strArray$1(vocabulary["estimates"], DEFAULT_VOCABULARY.estimates),
|
|
219349
|
-
vagueWords: strArray$1(vocabulary["vagueWords"], DEFAULT_VOCABULARY.vagueWords),
|
|
219350
|
-
verifyCommands: strArray$1(vocabulary["verifyCommands"], DEFAULT_VOCABULARY.verifyCommands),
|
|
219351
|
-
verifyPrefixes: strArray$1(vocabulary["verifyPrefixes"], DEFAULT_VOCABULARY.verifyPrefixes)
|
|
219352
|
-
},
|
|
219353
|
-
secrets: strArray$1(base["secrets"], []),
|
|
219354
|
-
roles: {
|
|
219355
|
-
proponents: num(roles["proponents"], DEFAULT_ROLES.proponents),
|
|
219356
|
-
defenders: num(roles["defenders"], DEFAULT_ROLES.defenders),
|
|
219357
|
-
adversaries: num(roles["adversaries"], DEFAULT_ROLES.adversaries),
|
|
219358
|
-
judges: num(roles["judges"], DEFAULT_ROLES.judges),
|
|
219359
|
-
refiners: num(roles["refiners"], DEFAULT_ROLES.refiners)
|
|
219360
|
-
},
|
|
219361
|
-
quorum: {
|
|
219362
|
-
minPoints: num(quorum["minPoints"], DEFAULT_QUORUM.minPoints),
|
|
219363
|
-
minAxes: num(quorum["minAxes"], DEFAULT_QUORUM.minAxes),
|
|
219364
|
-
axes: strArray$1(quorum["axes"], DEFAULT_QUORUM.axes)
|
|
219365
|
-
},
|
|
219366
|
-
loadedFrom,
|
|
219367
|
-
missingKeys: CONFIG_REQUIRED_KEYS.filter((key) => base[key] === void 0)
|
|
219368
|
-
};
|
|
219428
|
+
function writeJson(_fs, path, value) {
|
|
219429
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
219430
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
219369
219431
|
}
|
|
219370
|
-
function
|
|
219371
|
-
|
|
219372
|
-
const
|
|
219373
|
-
|
|
219374
|
-
|
|
219375
|
-
|
|
219376
|
-
} catch {
|
|
219377
|
-
return;
|
|
219432
|
+
function walk$1(fs, dir, accept, acc = []) {
|
|
219433
|
+
if (!fs.isDirectory(dir)) return acc;
|
|
219434
|
+
for (const name of fs.list(dir)) {
|
|
219435
|
+
const full = join(dir, name);
|
|
219436
|
+
if (fs.isDirectory(full)) walk$1(fs, full, accept, acc);
|
|
219437
|
+
else if (accept(full)) acc.push(full);
|
|
219378
219438
|
}
|
|
219439
|
+
return acc;
|
|
219379
219440
|
}
|
|
219380
|
-
|
|
219381
|
-
const resolvedRoot = resolve(root);
|
|
219382
|
-
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(resolvedRoot, candidate);
|
|
219383
|
-
if (resolved !== resolvedRoot && !resolved.startsWith(`${resolvedRoot}${sep}`)) throw new Error(`ruta fuera del workspace: ${candidate}`);
|
|
219384
|
-
return resolved;
|
|
219385
|
-
}
|
|
219386
|
-
var DEFAULT_LAYOUT, DEFAULT_THRESHOLDS, DEFAULT_VOCABULARY, DEFAULT_ROLES, DEFAULT_QUORUM, CONFIG_REQUIRED_KEYS;
|
|
219387
|
-
var init_config$6 = __esmMin((() => {
|
|
219388
|
-
DEFAULT_LAYOUT = {
|
|
219389
|
-
waves: "design/waves",
|
|
219390
|
-
backlog: "backlog",
|
|
219391
|
-
adr: "design/ADR",
|
|
219392
|
-
inventory: "inventory"
|
|
219393
|
-
};
|
|
219394
|
-
DEFAULT_THRESHOLDS = {
|
|
219395
|
-
minEpics: 1,
|
|
219396
|
-
minTasks: 1,
|
|
219397
|
-
minAcPerTask: 2,
|
|
219398
|
-
minDecisionBytes: 200,
|
|
219399
|
-
minArtifactBytes: 100,
|
|
219400
|
-
minBriefSections: 7,
|
|
219401
|
-
minContextBytes: 80,
|
|
219402
|
-
minGoalChars: 40,
|
|
219403
|
-
minScopeChars: 40,
|
|
219404
|
-
minFieldChars: 10,
|
|
219405
|
-
minMetricChars: 4,
|
|
219406
|
-
allowVerifyTargetMissing: false
|
|
219407
|
-
};
|
|
219408
|
-
DEFAULT_VOCABULARY = {
|
|
219409
|
-
areas: [
|
|
219410
|
-
"cliente",
|
|
219411
|
-
"seller",
|
|
219412
|
-
"agent",
|
|
219413
|
-
"admin",
|
|
219414
|
-
"plataforma"
|
|
219415
|
-
],
|
|
219416
|
-
requiredAreas: [],
|
|
219417
|
-
types: [
|
|
219418
|
-
"db",
|
|
219419
|
-
"api",
|
|
219420
|
-
"ui",
|
|
219421
|
-
"domain",
|
|
219422
|
-
"infra",
|
|
219423
|
-
"test",
|
|
219424
|
-
"docs",
|
|
219425
|
-
"app",
|
|
219426
|
-
"contract",
|
|
219427
|
-
"ops",
|
|
219428
|
-
"tooling"
|
|
219429
|
-
],
|
|
219430
|
-
estimates: [
|
|
219431
|
-
"XS",
|
|
219432
|
-
"S",
|
|
219433
|
-
"M",
|
|
219434
|
-
"L",
|
|
219435
|
-
"XL"
|
|
219436
|
-
],
|
|
219437
|
-
vagueWords: [
|
|
219438
|
-
"funciona",
|
|
219439
|
-
"correcto",
|
|
219440
|
-
"adecuado",
|
|
219441
|
-
"rapido",
|
|
219442
|
-
"robusto",
|
|
219443
|
-
"bonito"
|
|
219444
|
-
],
|
|
219445
|
-
verifyCommands: [
|
|
219446
|
-
"pnpm",
|
|
219447
|
-
"npm",
|
|
219448
|
-
"node",
|
|
219449
|
-
"bash",
|
|
219450
|
-
"sh",
|
|
219451
|
-
"make",
|
|
219452
|
-
"python",
|
|
219453
|
-
"go",
|
|
219454
|
-
"cargo",
|
|
219455
|
-
"dotnet"
|
|
219456
|
-
],
|
|
219457
|
-
verifyPrefixes: [
|
|
219458
|
-
"test/unit/",
|
|
219459
|
-
"test/db/",
|
|
219460
|
-
"test/domain/",
|
|
219461
|
-
"test/api/",
|
|
219462
|
-
"test/perf/",
|
|
219463
|
-
"e2e/",
|
|
219464
|
-
"scripts/checks/"
|
|
219465
|
-
]
|
|
219466
|
-
};
|
|
219467
|
-
DEFAULT_ROLES = {
|
|
219468
|
-
proponents: 3,
|
|
219469
|
-
defenders: 3,
|
|
219470
|
-
adversaries: 3,
|
|
219471
|
-
judges: 3,
|
|
219472
|
-
refiners: 2
|
|
219473
|
-
};
|
|
219474
|
-
DEFAULT_QUORUM = {
|
|
219475
|
-
minPoints: 1,
|
|
219476
|
-
minAxes: 2,
|
|
219477
|
-
axes: [
|
|
219478
|
-
"cobertura",
|
|
219479
|
-
"falsabilidad",
|
|
219480
|
-
"riesgo",
|
|
219481
|
-
"coste",
|
|
219482
|
-
"encaje"
|
|
219483
|
-
]
|
|
219484
|
-
};
|
|
219485
|
-
CONFIG_REQUIRED_KEYS = [
|
|
219486
|
-
"version",
|
|
219487
|
-
"layout",
|
|
219488
|
-
"waves",
|
|
219489
|
-
"thresholds",
|
|
219490
|
-
"vocabulary"
|
|
219491
|
-
];
|
|
219492
|
-
}));
|
|
219441
|
+
var init_fsJson = __esmMin((() => {}));
|
|
219493
219442
|
// ../../packages/agent-core-v2/src/features/wave/core/nodeFs.ts
|
|
219494
219443
|
var nodeWaveFs;
|
|
219495
219444
|
var init_nodeFs = __esmMin((() => {
|
|
@@ -219531,6 +219480,470 @@ var init_nodeFs = __esmMin((() => {
|
|
|
219531
219480
|
}
|
|
219532
219481
|
};
|
|
219533
219482
|
}));
|
|
219483
|
+
// ../../packages/agent-core-v2/src/features/wave/core/config.ts
|
|
219484
|
+
function seats(prefix, count) {
|
|
219485
|
+
return Array.from({ length: Math.max(0, count) }, (_, index) => `${prefix}${index + 1}`);
|
|
219486
|
+
}
|
|
219487
|
+
function waveRoundSeats(roles, round) {
|
|
219488
|
+
if (round === "propose") return seats("P", roles.proponents);
|
|
219489
|
+
if (round === "defend") return seats("D", roles.defenders);
|
|
219490
|
+
if (round === "attack") return seats("A", roles.adversaries);
|
|
219491
|
+
if (round === "judge") return seats("J", roles.judges);
|
|
219492
|
+
const refiners = seats("R", roles.refiners);
|
|
219493
|
+
return round === "refine" ? refiners.slice(0, 1) : refiners.slice(1);
|
|
219494
|
+
}
|
|
219495
|
+
function waveConfigState(config) {
|
|
219496
|
+
const state = config;
|
|
219497
|
+
return {
|
|
219498
|
+
...config,
|
|
219499
|
+
version: state.version ?? 1,
|
|
219500
|
+
wavesOpen: state.wavesOpen ?? [],
|
|
219501
|
+
raw: state.raw ?? {}
|
|
219502
|
+
};
|
|
219503
|
+
}
|
|
219504
|
+
function record$2(value) {
|
|
219505
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
219506
|
+
}
|
|
219507
|
+
function num(value, fallback) {
|
|
219508
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
219509
|
+
}
|
|
219510
|
+
function text(value, fallback) {
|
|
219511
|
+
return typeof value === "string" ? value : fallback;
|
|
219512
|
+
}
|
|
219513
|
+
function strArray$1(value, fallback) {
|
|
219514
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : fallback;
|
|
219515
|
+
}
|
|
219516
|
+
function makeWaveConfig(raw, loadedFrom) {
|
|
219517
|
+
const base = record$2(raw);
|
|
219518
|
+
const layout = record$2(base["layout"]);
|
|
219519
|
+
const thresholds = record$2(base["thresholds"]);
|
|
219520
|
+
const vocabulary = record$2(base["vocabulary"]);
|
|
219521
|
+
const roles = record$2(base["roles"]);
|
|
219522
|
+
const quorum = record$2(base["quorum"]);
|
|
219523
|
+
return {
|
|
219524
|
+
version: num(base["version"], 1),
|
|
219525
|
+
wavesOpen: strArray$1(base["wavesOpen"], []),
|
|
219526
|
+
raw: base,
|
|
219527
|
+
layout: {
|
|
219528
|
+
waves: text(layout["waves"], DEFAULT_LAYOUT.waves),
|
|
219529
|
+
backlog: text(layout["backlog"], DEFAULT_LAYOUT.backlog),
|
|
219530
|
+
adr: text(layout["adr"], DEFAULT_LAYOUT.adr),
|
|
219531
|
+
inventory: text(layout["inventory"], DEFAULT_LAYOUT.inventory)
|
|
219532
|
+
},
|
|
219533
|
+
waves: strArray$1(base["waves"], ["W0"]),
|
|
219534
|
+
thresholds: {
|
|
219535
|
+
minEpics: num(thresholds["minEpics"], DEFAULT_THRESHOLDS.minEpics),
|
|
219536
|
+
minTasks: num(thresholds["minTasks"], DEFAULT_THRESHOLDS.minTasks),
|
|
219537
|
+
minAcPerTask: num(thresholds["minAcPerTask"], DEFAULT_THRESHOLDS.minAcPerTask),
|
|
219538
|
+
minDecisionBytes: num(thresholds["minDecisionBytes"], DEFAULT_THRESHOLDS.minDecisionBytes),
|
|
219539
|
+
minArtifactBytes: num(thresholds["minArtifactBytes"], DEFAULT_THRESHOLDS.minArtifactBytes),
|
|
219540
|
+
minBriefSections: num(thresholds["minBriefSections"], DEFAULT_THRESHOLDS.minBriefSections),
|
|
219541
|
+
minContextBytes: num(thresholds["minContextBytes"], DEFAULT_THRESHOLDS.minContextBytes),
|
|
219542
|
+
minGoalChars: num(thresholds["minGoalChars"], DEFAULT_THRESHOLDS.minGoalChars),
|
|
219543
|
+
minScopeChars: num(thresholds["minScopeChars"], DEFAULT_THRESHOLDS.minScopeChars),
|
|
219544
|
+
minFieldChars: num(thresholds["minFieldChars"], DEFAULT_THRESHOLDS.minFieldChars),
|
|
219545
|
+
minMetricChars: num(thresholds["minMetricChars"], DEFAULT_THRESHOLDS.minMetricChars)
|
|
219546
|
+
},
|
|
219547
|
+
vocabulary: {
|
|
219548
|
+
areas: strArray$1(vocabulary["areas"], DEFAULT_VOCABULARY.areas),
|
|
219549
|
+
requiredAreas: strArray$1(vocabulary["requiredAreas"], DEFAULT_VOCABULARY.requiredAreas),
|
|
219550
|
+
types: strArray$1(vocabulary["types"], DEFAULT_VOCABULARY.types),
|
|
219551
|
+
estimates: strArray$1(vocabulary["estimates"], DEFAULT_VOCABULARY.estimates),
|
|
219552
|
+
vagueWords: strArray$1(vocabulary["vagueWords"], DEFAULT_VOCABULARY.vagueWords),
|
|
219553
|
+
verifyCommands: strArray$1(vocabulary["verifyCommands"], DEFAULT_VOCABULARY.verifyCommands),
|
|
219554
|
+
verifyPrefixes: strArray$1(vocabulary["verifyPrefixes"], DEFAULT_VOCABULARY.verifyPrefixes)
|
|
219555
|
+
},
|
|
219556
|
+
secrets: strArray$1(base["secrets"], []),
|
|
219557
|
+
roles: {
|
|
219558
|
+
proponents: num(roles["proponents"], DEFAULT_ROLES.proponents),
|
|
219559
|
+
defenders: num(roles["defenders"], DEFAULT_ROLES.defenders),
|
|
219560
|
+
adversaries: num(roles["adversaries"], DEFAULT_ROLES.adversaries),
|
|
219561
|
+
judges: num(roles["judges"], DEFAULT_ROLES.judges),
|
|
219562
|
+
refiners: num(roles["refiners"], DEFAULT_ROLES.refiners)
|
|
219563
|
+
},
|
|
219564
|
+
quorum: {
|
|
219565
|
+
minPoints: num(quorum["minPoints"], DEFAULT_QUORUM.minPoints),
|
|
219566
|
+
minAxes: num(quorum["minAxes"], DEFAULT_QUORUM.minAxes),
|
|
219567
|
+
axes: strArray$1(quorum["axes"], DEFAULT_QUORUM.axes)
|
|
219568
|
+
},
|
|
219569
|
+
loadedFrom
|
|
219570
|
+
};
|
|
219571
|
+
}
|
|
219572
|
+
function readWaveConfig(fs, root) {
|
|
219573
|
+
const file = resolve(root, "workflow.config.json");
|
|
219574
|
+
const raw = fs.read(file);
|
|
219575
|
+
if (raw === void 0) return void 0;
|
|
219576
|
+
try {
|
|
219577
|
+
return makeWaveConfig(JSON.parse(raw), file);
|
|
219578
|
+
} catch {
|
|
219579
|
+
return;
|
|
219580
|
+
}
|
|
219581
|
+
}
|
|
219582
|
+
function containedPath(root, candidate) {
|
|
219583
|
+
const resolvedRoot = resolve(root);
|
|
219584
|
+
const resolved = isAbsolute(candidate) ? resolve(candidate) : resolve(resolvedRoot, candidate);
|
|
219585
|
+
if (resolved !== resolvedRoot && !resolved.startsWith(`${resolvedRoot}${sep}`)) throw new Error(`ruta fuera del workspace: ${candidate}`);
|
|
219586
|
+
return resolved;
|
|
219587
|
+
}
|
|
219588
|
+
var WAVE_ROUNDS, WAVE_ROUND_DIRS, DEFAULT_LAYOUT, DEFAULT_THRESHOLDS, DEFAULT_VOCABULARY, DEFAULT_ROLES, DEFAULT_QUORUM;
|
|
219589
|
+
var init_config$6 = __esmMin((() => {
|
|
219590
|
+
WAVE_ROUNDS = [
|
|
219591
|
+
"propose",
|
|
219592
|
+
"defend",
|
|
219593
|
+
"attack",
|
|
219594
|
+
"judge",
|
|
219595
|
+
"refine",
|
|
219596
|
+
"audit"
|
|
219597
|
+
];
|
|
219598
|
+
WAVE_ROUND_DIRS = {
|
|
219599
|
+
propose: "01-proposals",
|
|
219600
|
+
defend: "02-defenses",
|
|
219601
|
+
attack: "03-attacks",
|
|
219602
|
+
judge: "04-verdicts",
|
|
219603
|
+
refine: "05-refined",
|
|
219604
|
+
audit: "05-refined"
|
|
219605
|
+
};
|
|
219606
|
+
DEFAULT_LAYOUT = {
|
|
219607
|
+
waves: "design/waves",
|
|
219608
|
+
backlog: "backlog",
|
|
219609
|
+
adr: "design/ADR",
|
|
219610
|
+
inventory: "inventory"
|
|
219611
|
+
};
|
|
219612
|
+
DEFAULT_THRESHOLDS = {
|
|
219613
|
+
minEpics: 1,
|
|
219614
|
+
minTasks: 1,
|
|
219615
|
+
minAcPerTask: 2,
|
|
219616
|
+
minDecisionBytes: 200,
|
|
219617
|
+
minArtifactBytes: 100,
|
|
219618
|
+
minBriefSections: 7,
|
|
219619
|
+
minContextBytes: 80,
|
|
219620
|
+
minGoalChars: 40,
|
|
219621
|
+
minScopeChars: 40,
|
|
219622
|
+
minFieldChars: 10,
|
|
219623
|
+
minMetricChars: 4
|
|
219624
|
+
};
|
|
219625
|
+
DEFAULT_VOCABULARY = {
|
|
219626
|
+
areas: [
|
|
219627
|
+
"cliente",
|
|
219628
|
+
"seller",
|
|
219629
|
+
"agent",
|
|
219630
|
+
"admin",
|
|
219631
|
+
"plataforma"
|
|
219632
|
+
],
|
|
219633
|
+
requiredAreas: [],
|
|
219634
|
+
types: [
|
|
219635
|
+
"db",
|
|
219636
|
+
"api",
|
|
219637
|
+
"ui",
|
|
219638
|
+
"domain",
|
|
219639
|
+
"infra",
|
|
219640
|
+
"test",
|
|
219641
|
+
"docs",
|
|
219642
|
+
"app",
|
|
219643
|
+
"contract",
|
|
219644
|
+
"ops",
|
|
219645
|
+
"tooling"
|
|
219646
|
+
],
|
|
219647
|
+
estimates: [
|
|
219648
|
+
"XS",
|
|
219649
|
+
"S",
|
|
219650
|
+
"M",
|
|
219651
|
+
"L",
|
|
219652
|
+
"XL"
|
|
219653
|
+
],
|
|
219654
|
+
vagueWords: [
|
|
219655
|
+
"funciona",
|
|
219656
|
+
"correcto",
|
|
219657
|
+
"adecuado",
|
|
219658
|
+
"rapido",
|
|
219659
|
+
"robusto",
|
|
219660
|
+
"bonito"
|
|
219661
|
+
],
|
|
219662
|
+
verifyCommands: [
|
|
219663
|
+
"pnpm",
|
|
219664
|
+
"npm",
|
|
219665
|
+
"node",
|
|
219666
|
+
"bash",
|
|
219667
|
+
"sh",
|
|
219668
|
+
"make",
|
|
219669
|
+
"python",
|
|
219670
|
+
"go",
|
|
219671
|
+
"cargo",
|
|
219672
|
+
"dotnet"
|
|
219673
|
+
],
|
|
219674
|
+
verifyPrefixes: [
|
|
219675
|
+
"test/unit/",
|
|
219676
|
+
"test/db/",
|
|
219677
|
+
"test/domain/",
|
|
219678
|
+
"test/api/",
|
|
219679
|
+
"test/perf/",
|
|
219680
|
+
"e2e/",
|
|
219681
|
+
"scripts/checks/"
|
|
219682
|
+
]
|
|
219683
|
+
};
|
|
219684
|
+
DEFAULT_ROLES = {
|
|
219685
|
+
proponents: 3,
|
|
219686
|
+
defenders: 3,
|
|
219687
|
+
adversaries: 3,
|
|
219688
|
+
judges: 3,
|
|
219689
|
+
refiners: 2
|
|
219690
|
+
};
|
|
219691
|
+
DEFAULT_QUORUM = {
|
|
219692
|
+
minPoints: 1,
|
|
219693
|
+
minAxes: 2,
|
|
219694
|
+
axes: [
|
|
219695
|
+
"cobertura",
|
|
219696
|
+
"falsabilidad",
|
|
219697
|
+
"riesgo",
|
|
219698
|
+
"coste",
|
|
219699
|
+
"encaje"
|
|
219700
|
+
]
|
|
219701
|
+
};
|
|
219702
|
+
}));
|
|
219703
|
+
// ../../packages/agent-core-v2/src/features/wave/core/seats.ts
|
|
219704
|
+
function contractedSeats(fs, registryFile) {
|
|
219705
|
+
const raw = fs.read(registryFile);
|
|
219706
|
+
if (raw === void 0) return void 0;
|
|
219707
|
+
try {
|
|
219708
|
+
return (JSON.parse(raw).seats ?? []).filter((seat) => typeof seat["round"] === "string" && typeof seat["role"] === "string").map((seat) => ({
|
|
219709
|
+
round: String(seat["round"]),
|
|
219710
|
+
role: String(seat["role"])
|
|
219711
|
+
}));
|
|
219712
|
+
} catch {
|
|
219713
|
+
return;
|
|
219714
|
+
}
|
|
219715
|
+
}
|
|
219716
|
+
function seatTicketHash(ticket) {
|
|
219717
|
+
return createHash("sha256").update(ticket).digest("hex");
|
|
219718
|
+
}
|
|
219719
|
+
function waveBase(input) {
|
|
219720
|
+
const fs = nodeWaveFs;
|
|
219721
|
+
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
219722
|
+
if (rawConfig === void 0) return { error: `no hay workflow.config.json en ${input.root}` };
|
|
219723
|
+
const wavesRel = makeWaveConfig(rawConfig).layout.waves;
|
|
219724
|
+
let wavesDir;
|
|
219725
|
+
try {
|
|
219726
|
+
wavesDir = containedPath(input.root, wavesRel);
|
|
219727
|
+
} catch (error) {
|
|
219728
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
219729
|
+
}
|
|
219730
|
+
const name = fs.list(wavesDir).filter((entry) => fs.isDirectory(join(wavesDir, entry))).find((entry) => entry === input.wave || entry.startsWith(`${input.wave}-`));
|
|
219731
|
+
if (name === void 0) return { error: `no existe la oleada ${input.wave} en ${wavesRel}` };
|
|
219732
|
+
return {
|
|
219733
|
+
base: join(wavesDir, name),
|
|
219734
|
+
wavesRel
|
|
219735
|
+
};
|
|
219736
|
+
}
|
|
219737
|
+
function runWaveContract(input) {
|
|
219738
|
+
const fs = nodeWaveFs;
|
|
219739
|
+
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
219740
|
+
if (rawConfig === void 0) return {
|
|
219741
|
+
output: `no hay workflow.config.json en ${input.root}`,
|
|
219742
|
+
seats: [],
|
|
219743
|
+
isError: true
|
|
219744
|
+
};
|
|
219745
|
+
const located = waveBase(input);
|
|
219746
|
+
if (located.base === void 0) return {
|
|
219747
|
+
output: located.error ?? "oleada no encontrada",
|
|
219748
|
+
seats: [],
|
|
219749
|
+
isError: true
|
|
219750
|
+
};
|
|
219751
|
+
const base = located.base;
|
|
219752
|
+
const roundDir = WAVE_ROUND_DIRS[input.round];
|
|
219753
|
+
const roles = waveRoundSeats(makeWaveConfig(rawConfig).roles, input.round);
|
|
219754
|
+
if (input.report === true) {
|
|
219755
|
+
const delivered = roles.filter((role) => fs.exists(join(base, roundDir, `${role}.md`)));
|
|
219756
|
+
const missing = roles.filter((role) => !delivered.includes(role));
|
|
219757
|
+
return {
|
|
219758
|
+
output: [
|
|
219759
|
+
`CONTRATOS ${input.round} de ${input.wave}: ${delivered.length}/${roles.length} entregados`,
|
|
219760
|
+
...roles.map((role) => `${delivered.includes(role) ? "ok " : "FIJA"} ${role} ${roundDir}/${role}.md`),
|
|
219761
|
+
...missing.length === 0 ? [] : ["", `faltan: ${missing.join(", ")}`]
|
|
219762
|
+
].join("\n"),
|
|
219763
|
+
seats: [],
|
|
219764
|
+
isError: missing.length > 0
|
|
219765
|
+
};
|
|
219766
|
+
}
|
|
219767
|
+
const declared = input.seats ?? [];
|
|
219768
|
+
for (const seat of declared) {
|
|
219769
|
+
if (seat.role !== void 0 && !roles.includes(seat.role)) return {
|
|
219770
|
+
output: `rol desconocido "${seat.role}" para la ronda ${input.round}: ${roles.join(", ")}`,
|
|
219771
|
+
seats: [],
|
|
219772
|
+
isError: true
|
|
219773
|
+
};
|
|
219774
|
+
if (seat.artifact !== void 0 && !seat.artifact.startsWith(`${roundDir}/`)) return {
|
|
219775
|
+
output: `el artefacto "${seat.artifact}" queda fuera de ${roundDir}/`,
|
|
219776
|
+
seats: [],
|
|
219777
|
+
isError: true
|
|
219778
|
+
};
|
|
219779
|
+
}
|
|
219780
|
+
const requested = declared.length === 0 ? roles.map((role) => ({ role })) : declared;
|
|
219781
|
+
const resolved = [];
|
|
219782
|
+
for (const [index, seat] of requested.entries()) {
|
|
219783
|
+
const role = seat.role ?? roles[index];
|
|
219784
|
+
if (role === void 0) return {
|
|
219785
|
+
output: "se contrataron más asientos que roles tiene la ronda",
|
|
219786
|
+
seats: [],
|
|
219787
|
+
isError: true
|
|
219788
|
+
};
|
|
219789
|
+
resolved.push({
|
|
219790
|
+
role,
|
|
219791
|
+
file: seat.artifact ?? `${roundDir}/${role}.md`
|
|
219792
|
+
});
|
|
219793
|
+
}
|
|
219794
|
+
const seatsDir = join(base, WAVE_SEATS_DIR);
|
|
219795
|
+
const entries = asArray$2(asRecord$2(readJson$2(fs, join(seatsDir, "seats.json")) ?? {})["seats"]).map(asRecord$2).filter((entry) => !resolved.some((seat) => entry["round"] === input.round && entry["role"] === seat.role));
|
|
219796
|
+
const contracts = [];
|
|
219797
|
+
for (const seat of resolved) {
|
|
219798
|
+
const ticket = randomBytes(16).toString("hex");
|
|
219799
|
+
fs.write(join(seatsDir, seat.role), `${seatTicketHash(ticket)}\n`);
|
|
219800
|
+
entries.push({
|
|
219801
|
+
role: seat.role,
|
|
219802
|
+
round: input.round,
|
|
219803
|
+
file: seat.file,
|
|
219804
|
+
ticket: seatTicketHash(ticket)
|
|
219805
|
+
});
|
|
219806
|
+
contracts.push({
|
|
219807
|
+
...seat,
|
|
219808
|
+
ticket,
|
|
219809
|
+
prompt: input.buildPrompt({
|
|
219810
|
+
wave: input.wave,
|
|
219811
|
+
round: input.round,
|
|
219812
|
+
...seat,
|
|
219813
|
+
ticket
|
|
219814
|
+
})
|
|
219815
|
+
});
|
|
219816
|
+
}
|
|
219817
|
+
writeJson(fs, join(seatsDir, "seats.json"), { seats: entries });
|
|
219818
|
+
return {
|
|
219819
|
+
output: [`CONTRATOS ${input.round} de ${input.wave}: ${contracts.length} asiento(s)`, ...contracts.map((contract) => `\n=== ${contract.role} -> ${contract.file}\n${contract.prompt}`)].join("\n"),
|
|
219820
|
+
seats: contracts
|
|
219821
|
+
};
|
|
219822
|
+
}
|
|
219823
|
+
var WAVE_SEATS_DIR, WAVE_CONTRACTS_FILE;
|
|
219824
|
+
var init_seats = __esmMin((() => {
|
|
219825
|
+
init_config$6();
|
|
219826
|
+
init_fsJson();
|
|
219827
|
+
init_nodeFs();
|
|
219828
|
+
WAVE_SEATS_DIR = ".seats";
|
|
219829
|
+
WAVE_CONTRACTS_FILE = `${WAVE_SEATS_DIR}/seats.json`;
|
|
219830
|
+
}));
|
|
219831
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/round/prompts.ts
|
|
219832
|
+
var SEAT_PRELUDE, ROLE_PROMPTS, JUDGE_BIASES;
|
|
219833
|
+
var init_prompts$2 = __esmMin((() => {
|
|
219834
|
+
SEAT_PRELUDE = [
|
|
219835
|
+
"Trabajas en una oleada de diseno con aislamiento de escritura.",
|
|
219836
|
+
"",
|
|
219837
|
+
"Reglas que no dependen de tu rol:",
|
|
219838
|
+
"- Escribe UN SOLO artefacto, entregado con WaveSubmit. No toques ningun otro fichero.",
|
|
219839
|
+
"- No modifiques el backlog, el codigo ni los artefactos de otros roles.",
|
|
219840
|
+
"- Todo lo que afirmes debe apoyarse en evidencia citables (ruta de fichero, dato del brief). Si no la tienes, escribe UNKNOWN con lo que falta. No lo rellenes con una invencion plausible.",
|
|
219841
|
+
"- Cada criterio de aceptacion que escribas debe poder fallar. Si no puedes describir el rojo esperado, el criterio no sirve."
|
|
219842
|
+
].join("\n");
|
|
219843
|
+
ROLE_PROMPTS = {
|
|
219844
|
+
propose: "Rol: proponente. Resuelve el brief de la forma mas simple que cubra el alcance completo, y demuestra que cubre. No propongas alternativas: elige una y defiendela. Incluye alcance con claves exactas, mecanismo concreto, tabla de epics y tasks, tres criterios de aceptacion completos con falsificador, coste y seccion UNKNOWN. No leas las propuestas de los otros proponentes: no existen todavia.",
|
|
219845
|
+
defend: "Rol: defensor de la propuesta que te asignan. Sostienla frente a las otras dos con evidencia y declara sus tres puntos mas fragiles antes de que los encuentre un adversario. Prohibido introducir mecanismos nuevos: si lo haces, estas proponiendo, no defendiendo.",
|
|
219846
|
+
attack: "Rol: adversario. No puntuas, no eliges favorita, no propones una cuarta propuesta. Caza, por este orden: criterios que no pueden fallar, huecos sin dueno, contradicciones internas, estados imposibles y seguridad. Cada hallazgo lleva id, propuesta afectada, seccion, la mutacion que lo demuestra y gravedad (bloqueante/alta/media/baja). Un hallazgo sin demostracion es una opinion.",
|
|
219847
|
+
judge: "Rol: juez. Puntua de 0 a 5 cada propuesta en los cinco ejes del brief y declara una preferencia con su margen. No redisenes. Penaliza sin piedad la falsabilidad: un criterio que no puede fallar resta, aunque el diseno sea bonito.",
|
|
219848
|
+
refine: "Rol: refinador integrador. Compone, no elige: toma el mejor mecanismo de cada propuesta y cierra los hallazgos del adversario. Tabla hallazgo -> cerrado/mitigado/abierto con disparador, criterios reescritos con su nuevo rojo esperado, coste resultante y deuda aceptada.",
|
|
219849
|
+
audit: "Rol: refinador adversarial, segunda pasada sin cortesia. Audita el refinamiento, caza criterios que no muerden, contrasta las cifras declaradas contra las reales, re-puntua con la misma rubrica y emite los parches obligatorios que falten. Si un parche es necesario y no lo emites, se pierde."
|
|
219850
|
+
};
|
|
219851
|
+
JUDGE_BIASES = [
|
|
219852
|
+
"coste",
|
|
219853
|
+
"falsabilidad",
|
|
219854
|
+
"encaje"
|
|
219855
|
+
];
|
|
219856
|
+
}));
|
|
219857
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/contract/contractRunner.ts
|
|
219858
|
+
function briefRel(root, wave) {
|
|
219859
|
+
const wavesRel = readJson$2(nodeWaveFs, join(root, "workflow.config.json"))?.layout?.waves ?? "design/waves";
|
|
219860
|
+
return `${wavesRel}/${nodeWaveFs.list(join(root, wavesRel)).find((entry) => entry === wave || entry.startsWith(`${wave}-`)) ?? wave}/00-brief.md`;
|
|
219861
|
+
}
|
|
219862
|
+
function runWaveContractForRoot(input) {
|
|
219863
|
+
const brief = briefRel(input.root, input.wave);
|
|
219864
|
+
return runWaveContract({
|
|
219865
|
+
...input,
|
|
219866
|
+
buildPrompt: (seat) => {
|
|
219867
|
+
const bias = input.round === "judge" ? JUDGE_BIASES[(Number(seat.role.slice(1)) - 1) % JUDGE_BIASES.length] : void 0;
|
|
219868
|
+
const lines = [
|
|
219869
|
+
SEAT_PRELUDE,
|
|
219870
|
+
"",
|
|
219871
|
+
ROLE_PROMPTS[input.round] ?? "",
|
|
219872
|
+
"",
|
|
219873
|
+
`Perfil: ${WAVE_SEAT_PROFILE}`,
|
|
219874
|
+
`Oleada: ${input.wave}. Brief: ${brief}.`,
|
|
219875
|
+
`Escribe: ${seat.file}.`,
|
|
219876
|
+
`Ticket de asiento: ${seat.ticket}. Es capacidad, no identidad: el contrato lo emitió para este asiento y WaveSubmit lo exige.`,
|
|
219877
|
+
`Entrega con WaveSubmit({ wave: "${input.wave}", round: "${input.round}", role: "${seat.role}", ticket: "${seat.ticket}", artifact: "..." }).`
|
|
219878
|
+
];
|
|
219879
|
+
if (bias !== void 0) lines.push(`Tu sesgo declarado es ${bias}: puntúa CON él, no contra él.`);
|
|
219880
|
+
return lines.join("\n");
|
|
219881
|
+
}
|
|
219882
|
+
});
|
|
219883
|
+
}
|
|
219884
|
+
var init_contractRunner = __esmMin((() => {
|
|
219885
|
+
init_fsJson();
|
|
219886
|
+
init_nodeFs();
|
|
219887
|
+
init_seats();
|
|
219888
|
+
init_prompts$2();
|
|
219889
|
+
init_wave$3();
|
|
219890
|
+
}));
|
|
219891
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/contract/contract.md?raw
|
|
219892
|
+
var contract_default;
|
|
219893
|
+
var init_contract$3 = __esmMin((() => {
|
|
219894
|
+
contract_default = "Create the round's contracts and hand each seat its exact prompt.\n\nReturns one contract per seat: `role`, `artifact` path, `ticket` and the ready-to-launch prompt. Launch one agent per contract with `Agent(subagent_type: \"wave-seat\")` (or `AgentSwarm` when the user enabled swarm) and pass the prompt unchanged — the ticket in it is what `WaveSubmit` accepts.\n\n- Seats and artifact paths come from `roles.*` in `workflow.config.json` and the round's directory. You may narrow them with `seats` (`role`, `artifact`), but an artifact must stay inside the round's directory.\n- You do not write artifacts: `WaveSubmit` is the seat's tool. Contract, launch, then read the results.\n- `report: true` lists which seats of the round have already delivered, without issuing tickets.\n\nClose the round with `WaveDecide` (judges), `WaveVerify` (tasks) and `WaveGate` (package). The wave is not closed until the gate is green.\n";
|
|
219895
|
+
}));
|
|
219896
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/contract/contractTool.ts
|
|
219897
|
+
var WaveContractTool;
|
|
219898
|
+
var init_contractTool = __esmMin((() => {
|
|
219899
|
+
init_sessionContext();
|
|
219900
|
+
init_input_schema();
|
|
219901
|
+
init_contract$4();
|
|
219902
|
+
init_contractRunner();
|
|
219903
|
+
init_contract$3();
|
|
219904
|
+
init_decorateParam();
|
|
219905
|
+
init_decorate();
|
|
219906
|
+
WaveContractTool = class WaveContractTool {
|
|
219907
|
+
sessionContext;
|
|
219908
|
+
name = "WaveContract";
|
|
219909
|
+
description = contract_default;
|
|
219910
|
+
parameters = toInputJsonSchema(WaveContractToolInputSchema);
|
|
219911
|
+
constructor(sessionContext) {
|
|
219912
|
+
this.sessionContext = sessionContext;
|
|
219913
|
+
}
|
|
219914
|
+
resolveExecution(args) {
|
|
219915
|
+
return {
|
|
219916
|
+
description: `Contracting ${args.round} seats of ${args.wave}`,
|
|
219917
|
+
approvalRule: this.name,
|
|
219918
|
+
execute: () => Promise.resolve(runWaveContractForRoot({
|
|
219919
|
+
root: args.root ?? this.sessionContext.cwd,
|
|
219920
|
+
wave: args.wave,
|
|
219921
|
+
round: args.round,
|
|
219922
|
+
seats: args.seats,
|
|
219923
|
+
report: args.report
|
|
219924
|
+
}))
|
|
219925
|
+
};
|
|
219926
|
+
}
|
|
219927
|
+
};
|
|
219928
|
+
WaveContractTool = __decorate([__decorateParam(0, ISessionContext)], WaveContractTool);
|
|
219929
|
+
}));
|
|
219930
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/decide/decide.ts
|
|
219931
|
+
var WaveDecideToolInputSchema, IWaveDecideTool;
|
|
219932
|
+
var init_decide$1 = __esmMin((() => {
|
|
219933
|
+
init_zod$1();
|
|
219934
|
+
init_instantiation();
|
|
219935
|
+
WaveDecideToolInputSchema = object$1({
|
|
219936
|
+
root: string().optional(),
|
|
219937
|
+
verdicts: array(object$1({
|
|
219938
|
+
judge: string().min(1),
|
|
219939
|
+
scores: record$3(string(), number$1())
|
|
219940
|
+
}).strict()).min(1),
|
|
219941
|
+
minPoints: number$1().optional(),
|
|
219942
|
+
minAxes: number$1().optional(),
|
|
219943
|
+
round: number$1().optional()
|
|
219944
|
+
}).strict();
|
|
219945
|
+
IWaveDecideTool = createDecorator("waveDecideTool");
|
|
219946
|
+
}));
|
|
219534
219947
|
// ../../packages/agent-core-v2/src/features/wave/core/quorum.ts
|
|
219535
219948
|
function median(values) {
|
|
219536
219949
|
const sorted = [...values].toSorted((left, right) => left - right);
|
|
@@ -219574,17 +219987,13 @@ function evaluateQuorum(input) {
|
|
|
219574
219987
|
if (winner === void 0) throw new Error("no hay propuestas que comparar");
|
|
219575
219988
|
if (second === void 0) return {
|
|
219576
219989
|
verdict: "refine",
|
|
219577
|
-
winner
|
|
219990
|
+
winner,
|
|
219578
219991
|
second: void 0,
|
|
219579
219992
|
medians,
|
|
219580
219993
|
medianMargin: 0,
|
|
219581
219994
|
judgesHoldingMargin: 0,
|
|
219582
|
-
perJudge:
|
|
219583
|
-
|
|
219584
|
-
margin: 0,
|
|
219585
|
-
holds: false
|
|
219586
|
-
})),
|
|
219587
|
-
reason: `solo hay una propuesta (${winner}): sin comparacion no hay quorum`
|
|
219995
|
+
perJudge: [],
|
|
219996
|
+
reason: `sin comparacion no hay quorum: solo hay una propuesta (${winner})`
|
|
219588
219997
|
};
|
|
219589
219998
|
const winnerMedian = medians[winner] ?? 0;
|
|
219590
219999
|
const secondMedian = medians[second] ?? 0;
|
|
@@ -219609,8 +220018,7 @@ function evaluateQuorum(input) {
|
|
|
219609
220018
|
});
|
|
219610
220019
|
const judgesHoldingMargin = perJudge.filter((entry) => entry.holds).length;
|
|
219611
220020
|
const marginOk = medianMargin >= minPoints;
|
|
219612
|
-
const
|
|
219613
|
-
const majorityOk = judgesHoldingMargin >= requiredJudges;
|
|
220021
|
+
const majorityOk = judgesHoldingMargin >= minAxes;
|
|
219614
220022
|
if (marginOk && majorityOk) return {
|
|
219615
220023
|
verdict: "adopt",
|
|
219616
220024
|
winner,
|
|
@@ -219619,9 +220027,9 @@ function evaluateQuorum(input) {
|
|
|
219619
220027
|
medianMargin,
|
|
219620
220028
|
judgesHoldingMargin,
|
|
219621
220029
|
perJudge,
|
|
219622
|
-
reason: `mediana ${winner} ${winnerMedian} vs ${second} ${secondMedian}: margen ${medianMargin} en ${judgesHoldingMargin}/${perJudge.length} jueces
|
|
220030
|
+
reason: `mediana ${winner} ${winnerMedian} vs ${second} ${secondMedian}: margen ${medianMargin} en ${judgesHoldingMargin}/${perJudge.length} jueces`
|
|
219623
220031
|
};
|
|
219624
|
-
const reason = [marginOk ? void 0 : `margen ${medianMargin} < ${minPoints}`, majorityOk ? void 0 : `solo ${judgesHoldingMargin}/${perJudge.length} jueces superan el margen (minimo ${
|
|
220032
|
+
const reason = [marginOk ? void 0 : `margen ${medianMargin} < ${minPoints}`, majorityOk ? void 0 : `solo ${judgesHoldingMargin}/${perJudge.length} jueces superan el margen (minimo ${minAxes})`].filter((part) => part !== void 0).join(" y ");
|
|
219625
220033
|
return {
|
|
219626
220034
|
verdict: round >= 2 ? "deadlock" : "refine",
|
|
219627
220035
|
winner,
|
|
@@ -219656,6 +220064,7 @@ function runWaveDecideForRoot(input) {
|
|
|
219656
220064
|
isError: true
|
|
219657
220065
|
};
|
|
219658
220066
|
}
|
|
220067
|
+
const holding = result.perJudge.length === 0 ? "sin comparacion" : `${result.judgesHoldingMargin}/${result.perJudge.length}`;
|
|
219659
220068
|
const lines = [
|
|
219660
220069
|
`QUORUM — ${result.verdict}`,
|
|
219661
220070
|
"",
|
|
@@ -219663,8 +220072,9 @@ function runWaveDecideForRoot(input) {
|
|
|
219663
220072
|
"",
|
|
219664
220073
|
` ganador: ${result.winner ?? "(empate)"}`,
|
|
219665
220074
|
` margen: ${result.medianMargin} (minimo ${input.minPoints ?? config.quorum.minPoints})`,
|
|
219666
|
-
` jueces con margen: ${
|
|
220075
|
+
` jueces con margen: ${holding} (minimo ${input.minAxes ?? config.quorum.minAxes})`,
|
|
219667
220076
|
...result.perJudge.map((entry) => ` ${entry.judge}: ${entry.margin}${entry.holds ? " ok" : " NO"}`),
|
|
220077
|
+
...result.perJudge.filter((entry) => entry.margin < 0).map((entry) => ` disidencia: ${entry.judge} ${entry.margin}`),
|
|
219668
220078
|
"",
|
|
219669
220079
|
` motivo: ${result.reason}`
|
|
219670
220080
|
];
|
|
@@ -219682,7 +220092,7 @@ var init_decideRunner = __esmMin((() => {
|
|
|
219682
220092
|
// ../../packages/agent-core-v2/src/features/wave/tools/decide/decide.md?raw
|
|
219683
220093
|
var decide_default;
|
|
219684
220094
|
var init_decide = __esmMin((() => {
|
|
219685
|
-
decide_default = "Compute the wave quorum from the judges' totals and say what may happen next.\n\nPass one entry per judge with its totals per proposal (`{ judge: \"J1\", scores: { P1: 17, P2: 15, P3: 14 } }`). The tool takes the **median** per proposal
|
|
220095
|
+
decide_default = "Compute the wave quorum from the judges' totals and say what may happen next.\n\nPass one entry per judge with its totals per proposal (`{ judge: \"J1\", scores: { P1: 17, P2: 15, P3: 14 } }`). The tool takes the **median** per proposal and applies both conditions of `core/quorum.ts`: the winner's median must beat the second's by `minPoints` (**margen de medianas**), and at least `minAxes` judges must give the winner that margin or more over the second (**mayoría de jueces**). Thresholds default to `workflow.config.json`.\n\nAnswers `adopt`, `refine` (no quorum yet, compose R1 and audit with R2) or `deadlock` (two rounds without quorum: adopt R1 with written dissent). A tie in the median, or a single proposal with nothing to compare, never crowns a winner and never counts as quorum.\n";
|
|
219686
220096
|
}));
|
|
219687
220097
|
// ../../packages/agent-core-v2/src/features/wave/tools/decide/decideTool.ts
|
|
219688
220098
|
var WaveDecideTool;
|
|
@@ -219729,531 +220139,196 @@ var init_gate$1 = __esmMin((() => {
|
|
|
219729
220139
|
}).strict();
|
|
219730
220140
|
IWaveGateTool = createDecorator("waveGateTool");
|
|
219731
220141
|
}));
|
|
219732
|
-
// ../../packages/agent-core-v2/src/features/wave/
|
|
219733
|
-
|
|
219734
|
-
|
|
219735
|
-
|
|
219736
|
-
|
|
219737
|
-
|
|
219738
|
-
|
|
219739
|
-
|
|
219740
|
-
|
|
219741
|
-
|
|
219742
|
-
|
|
219743
|
-
|
|
219744
|
-
|
|
219745
|
-
|
|
219746
|
-
|
|
219747
|
-
|
|
219748
|
-
|
|
219749
|
-
|
|
219750
|
-
|
|
219751
|
-
|
|
220142
|
+
// ../../packages/agent-core-v2/src/features/wave/core/verify/runner.ts
|
|
220143
|
+
function splitCommand(command) {
|
|
220144
|
+
const tokens = [];
|
|
220145
|
+
let current = "";
|
|
220146
|
+
let quote;
|
|
220147
|
+
for (const char of command) {
|
|
220148
|
+
if (quote !== void 0) {
|
|
220149
|
+
if (char === quote) quote = void 0;
|
|
220150
|
+
else current += char;
|
|
220151
|
+
continue;
|
|
220152
|
+
}
|
|
220153
|
+
if (char === "\"" || char === "'") {
|
|
220154
|
+
quote = char;
|
|
220155
|
+
continue;
|
|
220156
|
+
}
|
|
220157
|
+
if (SHELL_METACHARACTERS.has(char)) throw new Error(`metacaracter de shell prohibido en: ${command}`);
|
|
220158
|
+
if (char === " " || char === " ") {
|
|
220159
|
+
if (current !== "") {
|
|
220160
|
+
tokens.push(current);
|
|
220161
|
+
current = "";
|
|
220162
|
+
}
|
|
220163
|
+
continue;
|
|
220164
|
+
}
|
|
220165
|
+
current += char;
|
|
219752
220166
|
}
|
|
220167
|
+
if (quote !== void 0) throw new Error(`comillas sin cerrar en: ${command}`);
|
|
220168
|
+
if (current !== "") tokens.push(current);
|
|
220169
|
+
if (tokens.length === 0) throw new Error("comando vacio");
|
|
220170
|
+
return tokens;
|
|
219753
220171
|
}
|
|
219754
|
-
function
|
|
219755
|
-
|
|
219756
|
-
|
|
219757
|
-
|
|
219758
|
-
|
|
219759
|
-
}
|
|
219760
|
-
function asArray$2(value) {
|
|
219761
|
-
return Array.isArray(value) ? value : [];
|
|
219762
|
-
}
|
|
219763
|
-
function asText$1(value) {
|
|
219764
|
-
return typeof value === "string" ? value : "";
|
|
219765
|
-
}
|
|
219766
|
-
function writeJson(_fs, path, value) {
|
|
219767
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
219768
|
-
writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
219769
|
-
}
|
|
219770
|
-
function walk$1(fs, dir, accept, acc = []) {
|
|
219771
|
-
if (!fs.isDirectory(dir)) return acc;
|
|
219772
|
-
for (const name of fs.list(dir)) {
|
|
219773
|
-
const full = join(dir, name);
|
|
219774
|
-
if (fs.isDirectory(full)) walk$1(fs, full, accept, acc);
|
|
219775
|
-
else if (accept(full)) acc.push(full);
|
|
220172
|
+
function containPaths(argv, root) {
|
|
220173
|
+
for (const token of argv) {
|
|
220174
|
+
if (token.startsWith("-")) continue;
|
|
220175
|
+
if (!token.includes("/") && !/\.(mjs|cjs|js|ts|sh)$/.test(token)) continue;
|
|
220176
|
+
containedPath(root, token);
|
|
219776
220177
|
}
|
|
219777
|
-
return acc;
|
|
219778
|
-
}
|
|
219779
|
-
var init_fsJson = __esmMin((() => {}));
|
|
219780
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/open/openRunner.ts
|
|
219781
|
-
function slugify(name) {
|
|
219782
|
-
return name.normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "");
|
|
219783
220178
|
}
|
|
219784
|
-
function
|
|
219785
|
-
|
|
219786
|
-
const configFile = join(input.root, "workflow.config.json");
|
|
219787
|
-
const rawConfig = readJson$2(fs, configFile);
|
|
219788
|
-
if (rawConfig === void 0) return {
|
|
219789
|
-
output: `no hay workflow.config.json en ${input.root}`,
|
|
219790
|
-
isError: true
|
|
219791
|
-
};
|
|
219792
|
-
const layout = asRecord$2(asRecord$2(rawConfig)["layout"]);
|
|
219793
|
-
const wavesRel = typeof layout["waves"] === "string" ? layout["waves"] : "design/waves";
|
|
219794
|
-
let wavesDir;
|
|
220179
|
+
function runCommand$2(command, options) {
|
|
220180
|
+
let argv;
|
|
219795
220181
|
try {
|
|
219796
|
-
|
|
220182
|
+
argv = splitCommand(command);
|
|
220183
|
+
const binary = (argv[0] ?? "").replace(/\.exe$/i, "");
|
|
220184
|
+
const allowed = options.allowBinaries.map((item) => item.replace(/\.exe$/i, ""));
|
|
220185
|
+
if (!allowed.includes(binary)) throw new Error(`binario no permitido: ${binary} (permitidos: ${allowed.join(", ")})`);
|
|
220186
|
+
containPaths(argv, options.root);
|
|
219797
220187
|
} catch (error) {
|
|
219798
220188
|
return {
|
|
219799
|
-
|
|
219800
|
-
|
|
220189
|
+
ok: false,
|
|
220190
|
+
output: `rechazado: ${error instanceof Error ? error.message : String(error)}`,
|
|
220191
|
+
rejected: true
|
|
219801
220192
|
};
|
|
219802
220193
|
}
|
|
219803
|
-
const
|
|
219804
|
-
|
|
219805
|
-
|
|
219806
|
-
|
|
219807
|
-
|
|
219808
|
-
|
|
219809
|
-
const slug = slugify(input.name);
|
|
219810
|
-
if (slug === "") return {
|
|
219811
|
-
output: "el nombre de la oleada queda vacio al normalizarlo",
|
|
219812
|
-
isError: true
|
|
219813
|
-
};
|
|
219814
|
-
if (fs.list(wavesDir).some((name) => name === next || name.startsWith(`${next}-`))) return {
|
|
219815
|
-
output: `la oleada ${next} ya existe`,
|
|
219816
|
-
isError: true
|
|
219817
|
-
};
|
|
219818
|
-
const dir = join(wavesDir, `${next}-${slug}`);
|
|
219819
|
-
for (const sub of SUBDIRS) fs.mkdir(join(dir, sub));
|
|
219820
|
-
fs.write(join(dir, "00-brief.md"), BRIEF_SKELETON.replaceAll("{{WAVE}}", next).replaceAll("{{NAME}}", slug));
|
|
219821
|
-
const declared = asArray$2(asRecord$2(rawConfig)["waves"]).map(String);
|
|
219822
|
-
if (!declared.includes(next)) writeJson(fs, configFile, {
|
|
219823
|
-
...asRecord$2(rawConfig),
|
|
219824
|
-
waves: [...declared, next].toSorted()
|
|
220194
|
+
const result = spawnSync(argv[0] ?? "", argv.slice(1), {
|
|
220195
|
+
cwd: options.cwd ?? options.root,
|
|
220196
|
+
encoding: "utf8",
|
|
220197
|
+
timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS$1,
|
|
220198
|
+
stdio: "pipe",
|
|
220199
|
+
shell: false
|
|
219825
220200
|
});
|
|
219826
|
-
|
|
219827
|
-
|
|
219828
|
-
|
|
219829
|
-
|
|
219830
|
-
|
|
219831
|
-
}
|
|
219832
|
-
var SUBDIRS, BRIEF_SKELETON;
|
|
219833
|
-
var init_openRunner = __esmMin((() => {
|
|
219834
|
-
init_config$6();
|
|
219835
|
-
init_fsJson();
|
|
219836
|
-
init_nodeFs();
|
|
219837
|
-
SUBDIRS = [
|
|
219838
|
-
"01-proposals",
|
|
219839
|
-
"02-defenses",
|
|
219840
|
-
"03-attacks",
|
|
219841
|
-
"04-verdicts",
|
|
219842
|
-
"05-refined"
|
|
219843
|
-
];
|
|
219844
|
-
BRIEF_SKELETON = [
|
|
219845
|
-
"# {{WAVE}} — Brief: {{NAME}}",
|
|
219846
|
-
"",
|
|
219847
|
-
"## 1. Contexto vinculante",
|
|
219848
|
-
"",
|
|
219849
|
-
"## 2. Alcance",
|
|
219850
|
-
"",
|
|
219851
|
-
"## 3. Evidencia disponible",
|
|
219852
|
-
"",
|
|
219853
|
-
"## 4. Preguntas que esta oleada resuelve",
|
|
219854
|
-
"",
|
|
219855
|
-
"## 5. Formato de salida",
|
|
219856
|
-
"",
|
|
219857
|
-
"## 6. Reglas duras",
|
|
219858
|
-
"",
|
|
219859
|
-
"## 7. Rúbrica (0-5)",
|
|
219860
|
-
""
|
|
219861
|
-
].join("\n");
|
|
219862
|
-
}));
|
|
219863
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/open/open.md?raw
|
|
219864
|
-
var open_default;
|
|
219865
|
-
var init_open = __esmMin((() => {
|
|
219866
|
-
open_default = "Open a wave: create its artifact tree and a brief skeleton, and declare the wave in `workflow.config.json`.\n\nThe brief starts with the seven mandatory sections and nothing else — a brief that already contains the answer makes the twelve seats theatre. Fill it before launching any seat; the gate rejects a brief with fewer than seven sections.\n\nOpening a wave also declares it in the config, so the package gate will require its artifacts from then on.\n";
|
|
219867
|
-
}));
|
|
219868
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/open/openTool.ts
|
|
219869
|
-
var WaveOpenTool;
|
|
219870
|
-
var init_openTool = __esmMin((() => {
|
|
219871
|
-
init_sessionContext();
|
|
219872
|
-
init_input_schema();
|
|
219873
|
-
init_open$1();
|
|
219874
|
-
init_openRunner();
|
|
219875
|
-
init_open();
|
|
219876
|
-
init_decorateParam();
|
|
219877
|
-
init_decorate();
|
|
219878
|
-
WaveOpenTool = class WaveOpenTool {
|
|
219879
|
-
sessionContext;
|
|
219880
|
-
name = "WaveOpen";
|
|
219881
|
-
description = open_default;
|
|
219882
|
-
parameters = toInputJsonSchema(WaveOpenToolInputSchema);
|
|
219883
|
-
constructor(sessionContext) {
|
|
219884
|
-
this.sessionContext = sessionContext;
|
|
219885
|
-
}
|
|
219886
|
-
resolveExecution(args) {
|
|
219887
|
-
return {
|
|
219888
|
-
description: `Opening wave ${args.name}`,
|
|
219889
|
-
approvalRule: this.name,
|
|
219890
|
-
execute: () => Promise.resolve(runWaveOpenForRoot({
|
|
219891
|
-
root: args.root ?? this.sessionContext.cwd,
|
|
219892
|
-
name: args.name,
|
|
219893
|
-
id: args.id
|
|
219894
|
-
}))
|
|
219895
|
-
};
|
|
219896
|
-
}
|
|
220201
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}${result.error === void 0 ? "" : result.error.message}`.replaceAll(/\s+/g, " ").trim().slice(0, 300);
|
|
220202
|
+
if (result.error !== void 0) return {
|
|
220203
|
+
ok: false,
|
|
220204
|
+
output: `no se pudo ejecutar: ${output}`,
|
|
220205
|
+
rejected: false
|
|
219897
220206
|
};
|
|
219898
|
-
|
|
219899
|
-
|
|
219900
|
-
|
|
219901
|
-
|
|
219902
|
-
|
|
219903
|
-
init_zod$1();
|
|
219904
|
-
init_instantiation();
|
|
219905
|
-
WaveRoundToolInputSchema = object$1({
|
|
219906
|
-
wave: string().min(2),
|
|
219907
|
-
round: _enum([
|
|
219908
|
-
"propose",
|
|
219909
|
-
"defend",
|
|
219910
|
-
"attack",
|
|
219911
|
-
"judge",
|
|
219912
|
-
"refine",
|
|
219913
|
-
"audit"
|
|
219914
|
-
]),
|
|
219915
|
-
root: string().optional()
|
|
219916
|
-
}).strict();
|
|
219917
|
-
IWaveRoundTool = createDecorator("waveRoundTool");
|
|
219918
|
-
}));
|
|
219919
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/round/prompts.ts
|
|
219920
|
-
var SEAT_PRELUDE, ROLE_PROMPTS, JUDGE_BIASES;
|
|
219921
|
-
var init_prompts$2 = __esmMin((() => {
|
|
219922
|
-
SEAT_PRELUDE = [
|
|
219923
|
-
"Trabajas en una oleada de diseno con aislamiento de escritura.",
|
|
219924
|
-
"",
|
|
219925
|
-
"Reglas que no dependen de tu rol:",
|
|
219926
|
-
"- Escribe UN SOLO artefacto, entregado con WaveSubmit. No toques ningun otro fichero.",
|
|
219927
|
-
"- No modifiques el backlog, el codigo ni los artefactos de otros roles.",
|
|
219928
|
-
"- Todo lo que afirmes debe apoyarse en evidencia citables (ruta de fichero, dato del brief). Si no la tienes, escribe UNKNOWN con lo que falta. No lo rellenes con una invencion plausible.",
|
|
219929
|
-
"- Cada criterio de aceptacion que escribas debe poder fallar. Si no puedes describir el rojo esperado, el criterio no sirve."
|
|
219930
|
-
].join("\n");
|
|
219931
|
-
ROLE_PROMPTS = {
|
|
219932
|
-
propose: "Rol: proponente. Resuelve el brief de la forma mas simple que cubra el alcance completo, y demuestra que cubre. No propongas alternativas: elige una y defiendela. Incluye alcance con claves exactas, mecanismo concreto, tabla de epics y tasks, tres criterios de aceptacion completos con falsificador, coste y seccion UNKNOWN. No leas las propuestas de los otros proponentes: no existen todavia.",
|
|
219933
|
-
defend: "Rol: defensor de la propuesta que te asignan. Sostienla frente a las otras dos con evidencia y declara sus tres puntos mas fragiles antes de que los encuentre un adversario. Prohibido introducir mecanismos nuevos: si lo haces, estas proponiendo, no defendiendo.",
|
|
219934
|
-
attack: "Rol: adversario. No puntuas, no eliges favorita, no propones una cuarta propuesta. Caza, por este orden: criterios que no pueden fallar, huecos sin dueno, contradicciones internas, estados imposibles y seguridad. Cada hallazgo lleva id, propuesta afectada, seccion, la mutacion que lo demuestra y gravedad (bloqueante/alta/media/baja). Un hallazgo sin demostracion es una opinion.",
|
|
219935
|
-
judge: "Rol: juez. Puntua de 0 a 5 cada propuesta en los cinco ejes del brief y declara una preferencia con su margen. No redisenes. Penaliza sin piedad la falsabilidad: un criterio que no puede fallar resta, aunque el diseno sea bonito.",
|
|
219936
|
-
refine: "Rol: refinador integrador. Compone, no elige: toma el mejor mecanismo de cada propuesta y cierra los hallazgos del adversario. Tabla hallazgo -> cerrado/mitigado/abierto con disparador, criterios reescritos con su nuevo rojo esperado, coste resultante y deuda aceptada.",
|
|
219937
|
-
audit: "Rol: refinador adversarial, segunda pasada sin cortesia. Audita el refinamiento, caza criterios que no muerden, contrasta las cifras declaradas contra las reales, re-puntua con la misma rubrica y emite los parches obligatorios que falten. Si un parche es necesario y no lo emites, se pierde."
|
|
220207
|
+
return {
|
|
220208
|
+
ok: result.status === 0,
|
|
220209
|
+
output,
|
|
220210
|
+
rejected: false,
|
|
220211
|
+
status: result.status ?? void 0
|
|
219938
220212
|
};
|
|
219939
|
-
JUDGE_BIASES = [
|
|
219940
|
-
"coste",
|
|
219941
|
-
"falsabilidad",
|
|
219942
|
-
"encaje"
|
|
219943
|
-
];
|
|
219944
|
-
}));
|
|
219945
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/round/roundRunner.ts
|
|
219946
|
-
function range(prefix, count) {
|
|
219947
|
-
return Array.from({ length: Math.max(1, count) }, (_, index) => `${prefix}${index + 1}`);
|
|
219948
|
-
}
|
|
219949
|
-
function roleOf(cfg, round) {
|
|
219950
|
-
if (round === "propose") return cfg.proponents;
|
|
219951
|
-
if (round === "defend") return cfg.defenders;
|
|
219952
|
-
if (round === "attack") return cfg.adversaries;
|
|
219953
|
-
if (round === "judge") return cfg.judges;
|
|
219954
|
-
return 1;
|
|
219955
220213
|
}
|
|
219956
|
-
function
|
|
219957
|
-
|
|
219958
|
-
|
|
219959
|
-
|
|
219960
|
-
|
|
219961
|
-
|
|
219962
|
-
|
|
220214
|
+
function exitDetail(outcome) {
|
|
220215
|
+
return outcome.status === void 0 ? outcome.output : `exit ${outcome.status}: ${outcome.output}`;
|
|
220216
|
+
}
|
|
220217
|
+
function evaluateMutant(ac, verifyCommand, options) {
|
|
220218
|
+
const script = asText$1(asRecord$2(ac["falsifier"])["script"]);
|
|
220219
|
+
if (script === "") return {
|
|
220220
|
+
state: "declarado",
|
|
220221
|
+
detail: "sin falsifier.script: el AC queda declarado y cuenta como FALLO"
|
|
219963
220222
|
};
|
|
219964
|
-
const
|
|
219965
|
-
const
|
|
219966
|
-
|
|
219967
|
-
|
|
220223
|
+
const acId = asText$1(ac["id"]);
|
|
220224
|
+
const apply = runCommand$2(`${script} apply`, options);
|
|
220225
|
+
if (apply.rejected) return {
|
|
220226
|
+
state: "rechazado",
|
|
220227
|
+
detail: `apply rechazado (${script}, ${acId}): ${apply.output}`
|
|
220228
|
+
};
|
|
220229
|
+
let mutated;
|
|
220230
|
+
let restore;
|
|
219968
220231
|
try {
|
|
219969
|
-
|
|
219970
|
-
}
|
|
219971
|
-
|
|
219972
|
-
output: error instanceof Error ? error.message : String(error),
|
|
219973
|
-
seats: [],
|
|
219974
|
-
isError: true
|
|
219975
|
-
};
|
|
220232
|
+
if (apply.ok) mutated = runCommand$2(verifyCommand, options);
|
|
220233
|
+
} finally {
|
|
220234
|
+
restore = runCommand$2(`${script} restore`, options);
|
|
219976
220235
|
}
|
|
219977
|
-
const
|
|
219978
|
-
if (
|
|
219979
|
-
|
|
219980
|
-
|
|
219981
|
-
|
|
220236
|
+
const failures = [];
|
|
220237
|
+
if (!apply.ok) failures.push(`apply fallo (${script}, ${acId}) ${exitDetail(apply)}`);
|
|
220238
|
+
if (restore.rejected || !restore.ok) failures.push(`restore fallo (${script}, ${acId}), el arbol puede estar sucio: ${restore.output}`);
|
|
220239
|
+
if (failures.length > 0) return {
|
|
220240
|
+
state: "error",
|
|
220241
|
+
detail: failures.join(" · ")
|
|
219982
220242
|
};
|
|
219983
|
-
|
|
219984
|
-
|
|
219985
|
-
|
|
219986
|
-
output: `falta ${briefRel}`,
|
|
219987
|
-
seats: [],
|
|
219988
|
-
isError: true
|
|
220243
|
+
if (mutated === void 0) return {
|
|
220244
|
+
state: "error",
|
|
220245
|
+
detail: `no se ejecuto el verify con la mutacion de ${acId}`
|
|
219989
220246
|
};
|
|
219990
|
-
|
|
219991
|
-
|
|
219992
|
-
|
|
219993
|
-
|
|
219994
|
-
|
|
220247
|
+
if (mutated.ok) return {
|
|
220248
|
+
state: "sobrevive",
|
|
220249
|
+
detail: "el verify pasa con la mutacion aplicada: el AC no muerde"
|
|
220250
|
+
};
|
|
220251
|
+
if (!runCommand$2(verifyCommand, options).ok) return {
|
|
220252
|
+
state: "error",
|
|
220253
|
+
detail: "el verify no vuelve a verde tras restaurar"
|
|
219995
220254
|
};
|
|
219996
|
-
const roles = asRecord$2(config["roles"]);
|
|
219997
|
-
const counts = {
|
|
219998
|
-
proponents: typeof roles["proponents"] === "number" ? roles["proponents"] : 3,
|
|
219999
|
-
defenders: typeof roles["defenders"] === "number" ? roles["defenders"] : 3,
|
|
220000
|
-
adversaries: typeof roles["adversaries"] === "number" ? roles["adversaries"] : 3,
|
|
220001
|
-
judges: typeof roles["judges"] === "number" ? roles["judges"] : 3
|
|
220002
|
-
};
|
|
220003
|
-
const shape = ROUNDS[input.round];
|
|
220004
|
-
const seats = shape.roles(roleOf(counts, input.round)).map((role) => {
|
|
220005
|
-
const bias = input.round === "judge" ? JUDGE_BIASES[(Number(role.slice(1)) - 1) % JUDGE_BIASES.length] : void 0;
|
|
220006
|
-
const file = `${wavesRel}/${waveDir}/${shape.dir}/${role}.md`;
|
|
220007
|
-
const lines = [
|
|
220008
|
-
SEAT_PRELUDE,
|
|
220009
|
-
"",
|
|
220010
|
-
ROLE_PROMPTS[input.round] ?? "",
|
|
220011
|
-
"",
|
|
220012
|
-
`Oleada: ${input.wave}. Brief: ${briefRel}.`,
|
|
220013
|
-
`Escribe: ${file}.`,
|
|
220014
|
-
`Entrega con WaveSubmit({ wave: "${input.wave}", round: "${input.round}", role: "${role}", artifact: "..." }).`
|
|
220015
|
-
];
|
|
220016
|
-
if (bias !== void 0) lines.push(`Tu sesgo declarado es ${bias}: puntua CON el, no contra el.`);
|
|
220017
|
-
return {
|
|
220018
|
-
role,
|
|
220019
|
-
file,
|
|
220020
|
-
prompt: lines.join("\n")
|
|
220021
|
-
};
|
|
220022
|
-
});
|
|
220023
220255
|
return {
|
|
220024
|
-
|
|
220025
|
-
|
|
220256
|
+
state: "muerto",
|
|
220257
|
+
detail: "rojo con la mutacion, verde tras restaurar"
|
|
220026
220258
|
};
|
|
220027
220259
|
}
|
|
220028
|
-
|
|
220029
|
-
|
|
220030
|
-
|
|
220031
|
-
|
|
220032
|
-
|
|
220033
|
-
|
|
220034
|
-
|
|
220035
|
-
|
|
220036
|
-
dir: "01-proposals",
|
|
220037
|
-
roles: (count) => range("P", count)
|
|
220038
|
-
},
|
|
220039
|
-
defend: {
|
|
220040
|
-
dir: "02-defenses",
|
|
220041
|
-
roles: (count) => range("D", count)
|
|
220042
|
-
},
|
|
220043
|
-
attack: {
|
|
220044
|
-
dir: "03-attacks",
|
|
220045
|
-
roles: (count) => range("A", count)
|
|
220046
|
-
},
|
|
220047
|
-
judge: {
|
|
220048
|
-
dir: "04-verdicts",
|
|
220049
|
-
roles: (count) => range("J", count)
|
|
220050
|
-
},
|
|
220051
|
-
refine: {
|
|
220052
|
-
dir: "05-refined",
|
|
220053
|
-
roles: () => ["R1"]
|
|
220054
|
-
},
|
|
220055
|
-
audit: {
|
|
220056
|
-
dir: "05-refined",
|
|
220057
|
-
roles: () => ["R2"]
|
|
220058
|
-
}
|
|
220260
|
+
function selectTaskCriteria(fs, root, cfg, taskId, ac) {
|
|
220261
|
+
const tasksDir = containedPath(root, cfg.layout.backlog);
|
|
220262
|
+
const file = walk$1(fs, join(tasksDir, "tasks"), (path) => path.endsWith(`${taskId}.json`))[0];
|
|
220263
|
+
if (file === void 0) throw new Error(`no encuentro la task ${taskId} en ${cfg.layout.backlog}/tasks/`);
|
|
220264
|
+
const criteria = asArray$2(asRecord$2(readJson$2(fs, file))["ac"]).map(asRecord$2);
|
|
220265
|
+
if (ac === void 0) return {
|
|
220266
|
+
taskId,
|
|
220267
|
+
criteria
|
|
220059
220268
|
};
|
|
220060
|
-
|
|
220061
|
-
|
|
220062
|
-
|
|
220063
|
-
|
|
220064
|
-
|
|
220065
|
-
}));
|
|
220066
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/round/roundTool.ts
|
|
220067
|
-
var WaveRoundTool;
|
|
220068
|
-
var init_roundTool = __esmMin((() => {
|
|
220069
|
-
init_sessionContext();
|
|
220070
|
-
init_input_schema();
|
|
220071
|
-
init_round$1();
|
|
220072
|
-
init_roundRunner();
|
|
220073
|
-
init_round();
|
|
220074
|
-
init_decorateParam();
|
|
220075
|
-
init_decorate();
|
|
220076
|
-
WaveRoundTool = class WaveRoundTool {
|
|
220077
|
-
sessionContext;
|
|
220078
|
-
name = "WaveRound";
|
|
220079
|
-
description = round_default;
|
|
220080
|
-
parameters = toInputJsonSchema(WaveRoundToolInputSchema);
|
|
220081
|
-
constructor(sessionContext) {
|
|
220082
|
-
this.sessionContext = sessionContext;
|
|
220083
|
-
}
|
|
220084
|
-
resolveExecution(args) {
|
|
220085
|
-
return {
|
|
220086
|
-
description: `Planning ${args.round} for ${args.wave}`,
|
|
220087
|
-
approvalRule: this.name,
|
|
220088
|
-
execute: () => Promise.resolve(runWaveRoundForRoot({
|
|
220089
|
-
root: args.root ?? this.sessionContext.cwd,
|
|
220090
|
-
wave: args.wave,
|
|
220091
|
-
round: args.round
|
|
220092
|
-
}))
|
|
220093
|
-
};
|
|
220094
|
-
}
|
|
220269
|
+
const selected = criteria.filter((entry) => asText$1(entry["id"]) === ac);
|
|
220270
|
+
if (selected.length === 0) throw new Error(`no existe el criterio ${ac} en la task ${taskId}`);
|
|
220271
|
+
return {
|
|
220272
|
+
taskId,
|
|
220273
|
+
criteria: selected
|
|
220095
220274
|
};
|
|
220096
|
-
WaveRoundTool = __decorate([__decorateParam(0, ISessionContext)], WaveRoundTool);
|
|
220097
|
-
}));
|
|
220098
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submit.ts
|
|
220099
|
-
var WaveSubmitToolInputSchema, IWaveSubmitTool;
|
|
220100
|
-
var init_submit$1 = __esmMin((() => {
|
|
220101
|
-
init_zod$1();
|
|
220102
|
-
init_instantiation();
|
|
220103
|
-
WaveSubmitToolInputSchema = object$1({
|
|
220104
|
-
wave: string().min(2),
|
|
220105
|
-
round: _enum([
|
|
220106
|
-
"propose",
|
|
220107
|
-
"defend",
|
|
220108
|
-
"attack",
|
|
220109
|
-
"judge",
|
|
220110
|
-
"refine",
|
|
220111
|
-
"audit"
|
|
220112
|
-
]),
|
|
220113
|
-
role: string().min(2),
|
|
220114
|
-
artifact: string().min(1),
|
|
220115
|
-
replace: boolean$1().optional(),
|
|
220116
|
-
root: string().optional()
|
|
220117
|
-
}).strict();
|
|
220118
|
-
IWaveSubmitTool = createDecorator("waveSubmitTool");
|
|
220119
|
-
}));
|
|
220120
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitRunner.ts
|
|
220121
|
-
function slotNames(slot, roles) {
|
|
220122
|
-
const configured = roles[slot.role];
|
|
220123
|
-
const count = typeof configured === "number" && Number.isFinite(configured) ? Math.max(0, Math.floor(configured)) : 0;
|
|
220124
|
-
return Array.from({ length: count }, (_, index) => `${slot.prefix}${index + 1}`);
|
|
220125
220275
|
}
|
|
220126
|
-
function
|
|
220127
|
-
const
|
|
220128
|
-
const
|
|
220129
|
-
|
|
220130
|
-
|
|
220131
|
-
|
|
220132
|
-
|
|
220133
|
-
const fs = nodeWaveFs;
|
|
220134
|
-
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
220135
|
-
if (rawConfig === void 0) return {
|
|
220136
|
-
output: `no hay workflow.config.json en ${input.root}`,
|
|
220137
|
-
isError: true
|
|
220138
|
-
};
|
|
220139
|
-
const layout = asRecord$2(asRecord$2(rawConfig)["layout"]);
|
|
220140
|
-
const wavesRel = typeof layout["waves"] === "string" ? layout["waves"] : "design/waves";
|
|
220141
|
-
const slot = ROUND_SLOTS[input.round];
|
|
220142
|
-
const names = slotNames(slot, asRecord$2(asRecord$2(rawConfig)["roles"]));
|
|
220143
|
-
const accepted = input.round === "audit" ? names.filter((name) => name !== "R1") : input.round === "refine" ? names.slice(0, 1) : names;
|
|
220144
|
-
if (!accepted.includes(input.role)) return {
|
|
220145
|
-
output: `el rol "${input.role}" no pertenece a la ronda ${input.round} (esperado ${accepted.join(", ") || "ninguno configurado"})`,
|
|
220146
|
-
isError: true
|
|
220276
|
+
function verifyTask(fs, root, cfg, taskId, options) {
|
|
220277
|
+
const { criteria } = selectTaskCriteria(fs, root, cfg, taskId, options?.ac);
|
|
220278
|
+
const runOptions = {
|
|
220279
|
+
root,
|
|
220280
|
+
allowBinaries: cfg.vocabulary.verifyCommands,
|
|
220281
|
+
cwd: options?.cwd,
|
|
220282
|
+
timeoutMs: options?.timeoutMs
|
|
220147
220283
|
};
|
|
220148
|
-
|
|
220149
|
-
|
|
220150
|
-
|
|
220151
|
-
|
|
220152
|
-
|
|
220153
|
-
|
|
220154
|
-
|
|
220155
|
-
|
|
220284
|
+
const acs = [];
|
|
220285
|
+
let declared = 0;
|
|
220286
|
+
for (const ac of criteria) {
|
|
220287
|
+
const verifyCommand = asText$1(ac["verify"]);
|
|
220288
|
+
const verify = runCommand$2(verifyCommand, runOptions);
|
|
220289
|
+
const mutant = evaluateMutant(ac, verifyCommand, runOptions);
|
|
220290
|
+
if (mutant.state === "declarado") declared++;
|
|
220291
|
+
const declaredOk = options?.allowDeclared === true && mutant.state === "declarado";
|
|
220292
|
+
const ok = verify.ok && (mutant.state === "muerto" || declaredOk);
|
|
220293
|
+
acs.push({
|
|
220294
|
+
acId: asText$1(ac["id"]),
|
|
220295
|
+
verify,
|
|
220296
|
+
mutant,
|
|
220297
|
+
ok
|
|
220298
|
+
});
|
|
220156
220299
|
}
|
|
220157
|
-
|
|
220158
|
-
|
|
220159
|
-
|
|
220160
|
-
|
|
220161
|
-
|
|
220162
|
-
if (!fs.isDirectory(dir)) return {
|
|
220163
|
-
output: `falta el directorio ${slot.dir} en la oleada ${input.wave}`,
|
|
220164
|
-
isError: true
|
|
220165
|
-
};
|
|
220166
|
-
const file = join(dir, `${input.role}.md`);
|
|
220167
|
-
if (fs.exists(file) && input.replace !== true) return {
|
|
220168
|
-
output: `el asiento ${input.role} ya entrego su artefacto; un asiento escribe una vez (usa replace solo para relanzar un fallo)`,
|
|
220169
|
-
isError: true
|
|
220170
|
-
};
|
|
220171
|
-
if (input.artifact.trim() === "") return {
|
|
220172
|
-
output: "el artefacto esta vacio: un asiento que no escribe, fallo",
|
|
220173
|
-
isError: true
|
|
220300
|
+
return {
|
|
220301
|
+
taskId,
|
|
220302
|
+
acs,
|
|
220303
|
+
declared,
|
|
220304
|
+
ok: acs.length > 0 && acs.every((ac) => ac.ok)
|
|
220174
220305
|
};
|
|
220175
|
-
fs.write(file, input.artifact.endsWith("\n") ? input.artifact : `${input.artifact}\n`);
|
|
220176
|
-
return { output: `escrito ${wavesRel}/${base.split("/").pop()}/${slot.dir}/${input.role}.md` };
|
|
220177
220306
|
}
|
|
220178
|
-
var
|
|
220179
|
-
var
|
|
220307
|
+
var SHELL_METACHARACTERS, DEFAULT_TIMEOUT_MS$1;
|
|
220308
|
+
var init_runner = __esmMin((() => {
|
|
220180
220309
|
init_config$6();
|
|
220181
220310
|
init_fsJson();
|
|
220182
|
-
|
|
220183
|
-
|
|
220184
|
-
|
|
220185
|
-
|
|
220186
|
-
|
|
220187
|
-
|
|
220188
|
-
|
|
220189
|
-
|
|
220190
|
-
|
|
220191
|
-
|
|
220192
|
-
|
|
220193
|
-
|
|
220194
|
-
attack: {
|
|
220195
|
-
dir: "03-attacks",
|
|
220196
|
-
prefix: "A",
|
|
220197
|
-
role: "adversaries"
|
|
220198
|
-
},
|
|
220199
|
-
judge: {
|
|
220200
|
-
dir: "04-verdicts",
|
|
220201
|
-
prefix: "J",
|
|
220202
|
-
role: "judges"
|
|
220203
|
-
},
|
|
220204
|
-
refine: {
|
|
220205
|
-
dir: "05-refined",
|
|
220206
|
-
prefix: "R",
|
|
220207
|
-
role: "refiners"
|
|
220208
|
-
},
|
|
220209
|
-
audit: {
|
|
220210
|
-
dir: "05-refined",
|
|
220211
|
-
prefix: "R",
|
|
220212
|
-
role: "refiners"
|
|
220213
|
-
}
|
|
220214
|
-
};
|
|
220215
|
-
}));
|
|
220216
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submit.md?raw
|
|
220217
|
-
var submit_default;
|
|
220218
|
-
var init_submit = __esmMin((() => {
|
|
220219
|
-
submit_default = "Deliver the artifact for your seat. This is the only way a seat writes: the tool binds the role to its slot and refuses anything else.\n\nRole and round must match — `propose` accepts P1..Pn, `defend` D1..Dn, `attack` A1..An, `judge` J1..Jn, `refine` R1, `audit` R2. A seat writes once; use `replace` only to relaunch a failed seat after its artifact was already written.\n\nPass the artifact as the text/JSON body. An empty artifact is rejected: a seat that did not write has failed, and the round must be relaunched rather than summarized by the orchestrator.\n";
|
|
220220
|
-
}));
|
|
220221
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitTool.ts
|
|
220222
|
-
var WaveSubmitTool;
|
|
220223
|
-
var init_submitTool = __esmMin((() => {
|
|
220224
|
-
init_sessionContext();
|
|
220225
|
-
init_input_schema();
|
|
220226
|
-
init_submit$1();
|
|
220227
|
-
init_submitRunner();
|
|
220228
|
-
init_submit();
|
|
220229
|
-
init_decorateParam();
|
|
220230
|
-
init_decorate();
|
|
220231
|
-
WaveSubmitTool = class WaveSubmitTool {
|
|
220232
|
-
sessionContext;
|
|
220233
|
-
name = "WaveSubmit";
|
|
220234
|
-
description = submit_default;
|
|
220235
|
-
parameters = toInputJsonSchema(WaveSubmitToolInputSchema);
|
|
220236
|
-
constructor(sessionContext) {
|
|
220237
|
-
this.sessionContext = sessionContext;
|
|
220238
|
-
}
|
|
220239
|
-
resolveExecution(args) {
|
|
220240
|
-
return {
|
|
220241
|
-
description: `Submitting ${args.role}`,
|
|
220242
|
-
approvalRule: this.name,
|
|
220243
|
-
execute: () => Promise.resolve(runWaveSubmitForRoot({
|
|
220244
|
-
root: args.root ?? this.sessionContext.cwd,
|
|
220245
|
-
wave: args.wave,
|
|
220246
|
-
round: args.round,
|
|
220247
|
-
role: args.role,
|
|
220248
|
-
artifact: args.artifact,
|
|
220249
|
-
replace: args.replace
|
|
220250
|
-
}))
|
|
220251
|
-
};
|
|
220252
|
-
}
|
|
220253
|
-
};
|
|
220254
|
-
WaveSubmitTool = __decorate([__decorateParam(0, ISessionContext)], WaveSubmitTool);
|
|
220311
|
+
SHELL_METACHARACTERS = /* @__PURE__ */ new Set([
|
|
220312
|
+
"|",
|
|
220313
|
+
"&",
|
|
220314
|
+
";",
|
|
220315
|
+
"<",
|
|
220316
|
+
">",
|
|
220317
|
+
"`",
|
|
220318
|
+
"$",
|
|
220319
|
+
"\n",
|
|
220320
|
+
"\r"
|
|
220321
|
+
]);
|
|
220322
|
+
DEFAULT_TIMEOUT_MS$1 = 6e5;
|
|
220255
220323
|
}));
|
|
220256
220324
|
// ../../packages/agent-core-v2/src/features/wave/core/gate/checks.ts
|
|
220325
|
+
function measurableThreshold(text, units) {
|
|
220326
|
+
const low = normalize$1(text);
|
|
220327
|
+
if (OPERATOR_WITH_NUMBER.test(low)) return true;
|
|
220328
|
+
if (EXACT_VALUE.test(low)) return true;
|
|
220329
|
+
if (units.some((unit) => new RegExp(`\\d\\s*${escapeRegExp$1(unit)}\\b`).test(low))) return true;
|
|
220330
|
+
return low.split(/\s*(?:,|;|\by\b)\s*/).filter(Boolean).length >= 3;
|
|
220331
|
+
}
|
|
220257
220332
|
function record$1(value) {
|
|
220258
220333
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
220259
220334
|
}
|
|
@@ -220281,38 +220356,350 @@ function walk(fs, dir, accept, acc = []) {
|
|
|
220281
220356
|
}
|
|
220282
220357
|
return acc;
|
|
220283
220358
|
}
|
|
220284
|
-
function
|
|
220285
|
-
|
|
220359
|
+
function requiredArtifacts(cfg) {
|
|
220360
|
+
const required = ["00-brief.md"];
|
|
220361
|
+
for (const round of WAVE_ROUNDS) for (const seat of waveRoundSeats(cfg.roles, round)) required.push(`${WAVE_ROUND_DIRS[round]}/${seat}.md`);
|
|
220362
|
+
required.push(DECISION_FILE, "07-epics.json");
|
|
220363
|
+
return required;
|
|
220364
|
+
}
|
|
220365
|
+
function briefSections(text) {
|
|
220366
|
+
const sections = [];
|
|
220367
|
+
let current;
|
|
220368
|
+
for (const line of text.split("\n")) {
|
|
220369
|
+
const heading = /^##\s+(.+?)\s*$/.exec(line);
|
|
220370
|
+
if (heading !== null) {
|
|
220371
|
+
current = {
|
|
220372
|
+
title: heading[1] ?? "",
|
|
220373
|
+
body: []
|
|
220374
|
+
};
|
|
220375
|
+
sections.push(current);
|
|
220376
|
+
continue;
|
|
220377
|
+
}
|
|
220378
|
+
if (/^#\s+/.test(line)) {
|
|
220379
|
+
current = void 0;
|
|
220380
|
+
continue;
|
|
220381
|
+
}
|
|
220382
|
+
current?.body.push(line);
|
|
220383
|
+
}
|
|
220384
|
+
return sections.map((section) => ({
|
|
220385
|
+
title: section.title,
|
|
220386
|
+
body: section.body.join("\n").trim()
|
|
220387
|
+
}));
|
|
220286
220388
|
}
|
|
220287
|
-
function
|
|
220288
|
-
|
|
220289
|
-
if (/\b(ms|s|seg|segundos?|minutos?|filas?|bytes?|p95|peticiones?|veces|puntos?|codigo|status|exact\w*)\b/i.test(value)) return true;
|
|
220290
|
-
return /[a-z]/i.test(value) && !/^\d+(\s+\d+)+$/.test(value);
|
|
220389
|
+
function sectionKeyword(title) {
|
|
220390
|
+
return normalize$1(title).replace(/^\d+\.?\s*/, "").match(/[a-z0-9]+/)?.[0] ?? "";
|
|
220291
220391
|
}
|
|
220292
|
-
function
|
|
220293
|
-
return
|
|
220392
|
+
function decisionStrip(value) {
|
|
220393
|
+
return (value ?? "").replaceAll("*", "").trim();
|
|
220294
220394
|
}
|
|
220295
|
-
function
|
|
220296
|
-
|
|
220297
|
-
return resolved.startsWith(waveDir) && existsSync(resolved);
|
|
220395
|
+
function decisionSplitRow(line) {
|
|
220396
|
+
return line.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((cell) => cell.trim());
|
|
220298
220397
|
}
|
|
220299
|
-
function
|
|
220300
|
-
|
|
220301
|
-
|
|
220302
|
-
|
|
220303
|
-
|
|
220304
|
-
|
|
220398
|
+
function isDecisionSeparator(row) {
|
|
220399
|
+
return row.length > 0 && row.every((cell) => DECISION_SEPARATOR.test(decisionStrip(cell)));
|
|
220400
|
+
}
|
|
220401
|
+
function decisionTables(text) {
|
|
220402
|
+
const blocks = [];
|
|
220403
|
+
let current = [];
|
|
220404
|
+
for (const line of text.split("\n")) {
|
|
220405
|
+
if (line.trim().startsWith("|")) {
|
|
220406
|
+
current.push(decisionSplitRow(line));
|
|
220407
|
+
continue;
|
|
220408
|
+
}
|
|
220409
|
+
if (current.length > 0) blocks.push(current);
|
|
220410
|
+
current = [];
|
|
220305
220411
|
}
|
|
220306
|
-
|
|
220412
|
+
if (current.length > 0) blocks.push(current);
|
|
220413
|
+
return blocks.filter((block) => block.length >= 2).map((block) => ({
|
|
220414
|
+
header: block[0] ?? [],
|
|
220415
|
+
body: block.slice(1).filter((row) => !isDecisionSeparator(row) && row.length === (block[0] ?? []).length)
|
|
220416
|
+
}));
|
|
220307
220417
|
}
|
|
220308
|
-
function
|
|
220309
|
-
const
|
|
220310
|
-
|
|
220311
|
-
|
|
220312
|
-
|
|
220313
|
-
|
|
220314
|
-
|
|
220315
|
-
|
|
220418
|
+
function decisionNumber(cell) {
|
|
220419
|
+
const value = decisionStrip(cell);
|
|
220420
|
+
if (value === "") return void 0;
|
|
220421
|
+
const match = DECISION_LEADING_NUMBER.exec(value);
|
|
220422
|
+
return match === null ? void 0 : Number(match[0].replace(",", "."));
|
|
220423
|
+
}
|
|
220424
|
+
function decisionProposal(cell) {
|
|
220425
|
+
const value = decisionStrip(cell);
|
|
220426
|
+
if (value === "") return void 0;
|
|
220427
|
+
return DECISION_PROPOSAL.test(value.toLowerCase()) ? value.toUpperCase() : void 0;
|
|
220428
|
+
}
|
|
220429
|
+
function decisionAxis(row, axes) {
|
|
220430
|
+
const low = normalize$1(decisionStrip(row));
|
|
220431
|
+
if (low === "") return void 0;
|
|
220432
|
+
const exact = axes.find((axis) => normalize$1(axis) === low);
|
|
220433
|
+
if (exact !== void 0) return exact;
|
|
220434
|
+
return axes.find((axis) => low.includes(normalize$1(axis)));
|
|
220435
|
+
}
|
|
220436
|
+
function isDecisionTotal(cell) {
|
|
220437
|
+
return /\btotal\b/.test(normalize$1(decisionStrip(cell)));
|
|
220438
|
+
}
|
|
220439
|
+
function isDecisionMedian(cell) {
|
|
220440
|
+
return /\bmedian/.test(normalize$1(decisionStrip(cell)));
|
|
220441
|
+
}
|
|
220442
|
+
function decisionColumn(header, predicate) {
|
|
220443
|
+
return header.findIndex((cell) => predicate(cell));
|
|
220444
|
+
}
|
|
220445
|
+
function findDecisionMatrix(blocks, axes) {
|
|
220446
|
+
let best;
|
|
220447
|
+
for (const block of blocks) {
|
|
220448
|
+
const header = block.header.map(decisionStrip);
|
|
220449
|
+
const columnProposals = header.filter((cell) => decisionProposal(cell) !== void 0);
|
|
220450
|
+
const rowProposals = block.body.filter((row) => decisionProposal(row[0]) !== void 0);
|
|
220451
|
+
const axisColumns = header.filter((cell) => decisionAxis(cell, axes) !== void 0 && !isDecisionTotal(cell) && !isDecisionMedian(cell));
|
|
220452
|
+
const axisRows = block.body.filter((row) => decisionAxis(row[0], axes) !== void 0);
|
|
220453
|
+
const byColumn = columnProposals.length >= 2 && axisRows.length > 0;
|
|
220454
|
+
const byRow = rowProposals.length >= 2 && axisColumns.length > 0;
|
|
220455
|
+
if (!byColumn && !byRow) continue;
|
|
220456
|
+
const score = Math.max(axisRows.length, axisColumns.length) * 10 + Math.max(columnProposals.length, rowProposals.length);
|
|
220457
|
+
if (best === void 0 || score > best.score) best = {
|
|
220458
|
+
block,
|
|
220459
|
+
orientation: byColumn ? "columns" : "rows",
|
|
220460
|
+
score
|
|
220461
|
+
};
|
|
220462
|
+
}
|
|
220463
|
+
return best;
|
|
220464
|
+
}
|
|
220465
|
+
function readDecisionColumns(block, axes, proposals, found) {
|
|
220466
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
220467
|
+
for (const [index, cell] of block.header.entries()) {
|
|
220468
|
+
const proposal = decisionProposal(cell);
|
|
220469
|
+
if (proposal !== void 0 && !indexes.has(proposal)) indexes.set(proposal, index);
|
|
220470
|
+
}
|
|
220471
|
+
for (const row of block.body) {
|
|
220472
|
+
const axis = decisionAxis(row[0], axes);
|
|
220473
|
+
if (axis === void 0 || found.has(axis)) continue;
|
|
220474
|
+
const cells = {};
|
|
220475
|
+
found.set(axis, {
|
|
220476
|
+
label: decisionStrip(row[0]),
|
|
220477
|
+
cells
|
|
220478
|
+
});
|
|
220479
|
+
for (const proposal of proposals) {
|
|
220480
|
+
const index = indexes.get(proposal);
|
|
220481
|
+
cells[proposal] = index === void 0 ? void 0 : decisionNumber(row[index]);
|
|
220482
|
+
}
|
|
220483
|
+
}
|
|
220484
|
+
return indexes;
|
|
220485
|
+
}
|
|
220486
|
+
function readDecisionRows(block, axes, found) {
|
|
220487
|
+
const columns = [];
|
|
220488
|
+
for (const [index, cell] of block.header.entries()) {
|
|
220489
|
+
const axis = decisionAxis(cell, axes);
|
|
220490
|
+
if (axis === void 0 || isDecisionTotal(cell) || isDecisionMedian(cell)) continue;
|
|
220491
|
+
columns.push({
|
|
220492
|
+
axis,
|
|
220493
|
+
index,
|
|
220494
|
+
label: decisionStrip(cell)
|
|
220495
|
+
});
|
|
220496
|
+
}
|
|
220497
|
+
const seen = [];
|
|
220498
|
+
for (const row of block.body) {
|
|
220499
|
+
const proposal = decisionProposal(row[0]);
|
|
220500
|
+
if (proposal === void 0) continue;
|
|
220501
|
+
if (!seen.includes(proposal)) seen.push(proposal);
|
|
220502
|
+
for (const column of columns) {
|
|
220503
|
+
const existing = found.get(column.axis);
|
|
220504
|
+
const entry = existing ?? {
|
|
220505
|
+
label: column.label,
|
|
220506
|
+
cells: {}
|
|
220507
|
+
};
|
|
220508
|
+
if (existing === void 0) found.set(column.axis, entry);
|
|
220509
|
+
if (entry.cells[proposal] !== void 0) continue;
|
|
220510
|
+
entry.cells[proposal] = decisionNumber(row[column.index]);
|
|
220511
|
+
}
|
|
220512
|
+
}
|
|
220513
|
+
return seen;
|
|
220514
|
+
}
|
|
220515
|
+
function decisionDeclarations(blocks, matrix, proposals) {
|
|
220516
|
+
const totals = {};
|
|
220517
|
+
const medians = {};
|
|
220518
|
+
const take = (target, proposal, value) => {
|
|
220519
|
+
if (proposal === void 0 || value === void 0 || target[proposal] !== void 0) return;
|
|
220520
|
+
target[proposal] = value;
|
|
220521
|
+
};
|
|
220522
|
+
if (matrix !== void 0) {
|
|
220523
|
+
const header = matrix.block.header.map(decisionStrip);
|
|
220524
|
+
const totalColumn = matrix.orientation === "rows" ? decisionColumn(header, isDecisionTotal) : -1;
|
|
220525
|
+
const medianColumn = matrix.orientation === "rows" ? decisionColumn(header, isDecisionMedian) : -1;
|
|
220526
|
+
for (const row of matrix.block.body) {
|
|
220527
|
+
const proposal = decisionProposal(row[0]);
|
|
220528
|
+
if (proposal !== void 0) {
|
|
220529
|
+
if (totalColumn !== -1) take(totals, proposal, decisionNumber(row[totalColumn]));
|
|
220530
|
+
if (medianColumn !== -1) take(medians, proposal, decisionNumber(row[medianColumn]));
|
|
220531
|
+
continue;
|
|
220532
|
+
}
|
|
220533
|
+
if (isDecisionTotal(row[0]) || isDecisionMedian(row[0])) {
|
|
220534
|
+
const target = isDecisionTotal(row[0]) ? totals : medians;
|
|
220535
|
+
for (const item of proposals) {
|
|
220536
|
+
const index = header.findIndex((cell) => decisionProposal(cell) === item);
|
|
220537
|
+
take(target, item, index === -1 ? void 0 : decisionNumber(row[index]));
|
|
220538
|
+
}
|
|
220539
|
+
}
|
|
220540
|
+
}
|
|
220541
|
+
}
|
|
220542
|
+
for (const block of blocks) {
|
|
220543
|
+
const header = block.header.map(decisionStrip);
|
|
220544
|
+
const totalColumn = decisionColumn(header, isDecisionTotal);
|
|
220545
|
+
const medianColumn = decisionColumn(header, isDecisionMedian);
|
|
220546
|
+
if (totalColumn === -1 && medianColumn === -1) continue;
|
|
220547
|
+
for (const row of block.body) {
|
|
220548
|
+
const proposal = decisionProposal(row[0]);
|
|
220549
|
+
if (proposal === void 0) continue;
|
|
220550
|
+
if (totalColumn !== -1) take(totals, proposal, decisionNumber(row[totalColumn]));
|
|
220551
|
+
if (medianColumn !== -1) take(medians, proposal, decisionNumber(row[medianColumn]));
|
|
220552
|
+
}
|
|
220553
|
+
}
|
|
220554
|
+
return {
|
|
220555
|
+
totals,
|
|
220556
|
+
medians
|
|
220557
|
+
};
|
|
220558
|
+
}
|
|
220559
|
+
function decisionMargins(blocks) {
|
|
220560
|
+
for (const block of blocks) {
|
|
220561
|
+
const header = block.header.map(decisionStrip);
|
|
220562
|
+
const judgeColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("juez"));
|
|
220563
|
+
const marginColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("margen"));
|
|
220564
|
+
if (judgeColumn === -1 || marginColumn === -1) continue;
|
|
220565
|
+
const preferColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("prefer"));
|
|
220566
|
+
const rows = [];
|
|
220567
|
+
for (const row of block.body) {
|
|
220568
|
+
const judge = decisionStrip(row[judgeColumn]);
|
|
220569
|
+
if (!DECISION_JUDGE.test(judge)) continue;
|
|
220570
|
+
const margin = DECISION_SIGNED_MARGIN.exec(decisionStrip(row[marginColumn]));
|
|
220571
|
+
if (margin === null) continue;
|
|
220572
|
+
rows.push({
|
|
220573
|
+
judge,
|
|
220574
|
+
margin: Number((margin[1] ?? "0").replace(",", ".")),
|
|
220575
|
+
prefers: preferColumn === -1 ? void 0 : decisionProposal(row[preferColumn])
|
|
220576
|
+
});
|
|
220577
|
+
}
|
|
220578
|
+
if (rows.length > 0) return rows;
|
|
220579
|
+
}
|
|
220580
|
+
return [];
|
|
220581
|
+
}
|
|
220582
|
+
function decisionDissent(text) {
|
|
220583
|
+
const lines = text.split("\n");
|
|
220584
|
+
const start = lines.findIndex((line) => /^#{1,3}\s+\d*\.?\s*disidencias/i.test(line));
|
|
220585
|
+
if (start === -1) return void 0;
|
|
220586
|
+
const level = /^(#{1,3})/.exec(lines[start] ?? "")?.[1]?.length ?? 1;
|
|
220587
|
+
const collected = [];
|
|
220588
|
+
for (const line of lines.slice(start + 1)) {
|
|
220589
|
+
const heading = /^(#{1,3})\s+\S/.exec(line);
|
|
220590
|
+
if (heading !== null && (heading[1] ?? "").length <= level) break;
|
|
220591
|
+
collected.push(line);
|
|
220592
|
+
}
|
|
220593
|
+
return collected.join("\n").trim();
|
|
220594
|
+
}
|
|
220595
|
+
function parseDecisionMatrix(text, options) {
|
|
220596
|
+
const axes = options.axes.map(String);
|
|
220597
|
+
const blocks = decisionTables(text);
|
|
220598
|
+
const matrix = findDecisionMatrix(blocks, axes);
|
|
220599
|
+
const found = /* @__PURE__ */ new Map();
|
|
220600
|
+
let proposals = options.proposals.map(String);
|
|
220601
|
+
let present = [];
|
|
220602
|
+
if (matrix !== void 0) {
|
|
220603
|
+
if (matrix.orientation === "columns") {
|
|
220604
|
+
if (proposals.length === 0) proposals = matrix.block.header.map(decisionStrip).map(decisionProposal).filter((label) => label !== void 0);
|
|
220605
|
+
const indexes = readDecisionColumns(matrix.block, axes, proposals, found);
|
|
220606
|
+
present = proposals.filter((proposal) => indexes.has(proposal));
|
|
220607
|
+
} else {
|
|
220608
|
+
if (proposals.length === 0) proposals = matrix.block.body.map((row) => decisionProposal(row[0])).filter((label) => label !== void 0);
|
|
220609
|
+
const seen = readDecisionRows(matrix.block, axes, found);
|
|
220610
|
+
present = proposals.filter((proposal) => seen.includes(proposal));
|
|
220611
|
+
}
|
|
220612
|
+
}
|
|
220613
|
+
const axisRows = [];
|
|
220614
|
+
const cells = [];
|
|
220615
|
+
const missing = [];
|
|
220616
|
+
for (const axis of axes) {
|
|
220617
|
+
const row = found.get(axis);
|
|
220618
|
+
if (row === void 0) continue;
|
|
220619
|
+
axisRows.push({
|
|
220620
|
+
axis,
|
|
220621
|
+
label: row.label,
|
|
220622
|
+
cells: row.cells
|
|
220623
|
+
});
|
|
220624
|
+
for (const proposal of present) {
|
|
220625
|
+
const value = row.cells[proposal];
|
|
220626
|
+
if (typeof value === "number") cells.push({
|
|
220627
|
+
axis,
|
|
220628
|
+
proposal,
|
|
220629
|
+
value
|
|
220630
|
+
});
|
|
220631
|
+
else missing.push({
|
|
220632
|
+
axis,
|
|
220633
|
+
proposal
|
|
220634
|
+
});
|
|
220635
|
+
}
|
|
220636
|
+
}
|
|
220637
|
+
const declarations = decisionDeclarations(blocks, matrix, proposals);
|
|
220638
|
+
const axesFound = axisRows.map((row) => row.axis);
|
|
220639
|
+
return {
|
|
220640
|
+
present: matrix !== void 0,
|
|
220641
|
+
orientation: matrix?.orientation,
|
|
220642
|
+
header: matrix === void 0 ? [] : matrix.block.header.map(decisionStrip),
|
|
220643
|
+
proposals,
|
|
220644
|
+
presentProposals: present,
|
|
220645
|
+
axisRows,
|
|
220646
|
+
cells,
|
|
220647
|
+
missing,
|
|
220648
|
+
axesFound,
|
|
220649
|
+
axesMissing: axes.filter((axis) => !axesFound.includes(axis)),
|
|
220650
|
+
totals: declarations.totals,
|
|
220651
|
+
medians: declarations.medians,
|
|
220652
|
+
margins: decisionMargins(blocks),
|
|
220653
|
+
dissent: decisionDissent(text)
|
|
220654
|
+
};
|
|
220655
|
+
}
|
|
220656
|
+
function decisionProposalSum(matrix, proposal) {
|
|
220657
|
+
const values = matrix.axisRows.map((row) => row.cells[proposal]);
|
|
220658
|
+
if (values.length === 0) return void 0;
|
|
220659
|
+
let total = 0;
|
|
220660
|
+
for (const value of values) {
|
|
220661
|
+
if (typeof value !== "number") return void 0;
|
|
220662
|
+
total += value;
|
|
220663
|
+
}
|
|
220664
|
+
return total;
|
|
220665
|
+
}
|
|
220666
|
+
function decisionMedian(values) {
|
|
220667
|
+
if (values.length === 0) return void 0;
|
|
220668
|
+
const sorted = [...values].toSorted((left, right) => left - right);
|
|
220669
|
+
const middle = Math.floor(sorted.length / 2);
|
|
220670
|
+
const current = sorted[middle];
|
|
220671
|
+
if (current === void 0) return void 0;
|
|
220672
|
+
if (sorted.length % 2 === 1) return current;
|
|
220673
|
+
const previous = sorted[middle - 1];
|
|
220674
|
+
return previous === void 0 ? void 0 : (previous + current) / 2;
|
|
220675
|
+
}
|
|
220676
|
+
function decisionRecalculateMedians(verdicts, options) {
|
|
220677
|
+
const tables = [];
|
|
220678
|
+
const missing = [];
|
|
220679
|
+
for (const verdict of verdicts) {
|
|
220680
|
+
const matrix = parseDecisionMatrix(verdict.text, options);
|
|
220681
|
+
if (!(matrix.present && matrix.axesMissing.length === 0 && matrix.missing.length === 0)) {
|
|
220682
|
+
missing.push(verdict.file);
|
|
220683
|
+
continue;
|
|
220684
|
+
}
|
|
220685
|
+
const totals = {};
|
|
220686
|
+
for (const proposal of matrix.proposals) totals[proposal] = decisionProposalSum(matrix, proposal) ?? NaN;
|
|
220687
|
+
tables.push({
|
|
220688
|
+
file: verdict.file,
|
|
220689
|
+
totals
|
|
220690
|
+
});
|
|
220691
|
+
}
|
|
220692
|
+
const medians = {};
|
|
220693
|
+
if (missing.length === 0 && tables.length > 0) for (const proposal of options.proposals) {
|
|
220694
|
+
const values = tables.map((entry) => entry.totals[proposal]).filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
220695
|
+
if (values.length !== tables.length) continue;
|
|
220696
|
+
const value = decisionMedian(values);
|
|
220697
|
+
if (value !== void 0) medians[proposal] = value;
|
|
220698
|
+
}
|
|
220699
|
+
return {
|
|
220700
|
+
medians,
|
|
220701
|
+
missing
|
|
220702
|
+
};
|
|
220316
220703
|
}
|
|
220317
220704
|
function runWaveGate(fs, root, cfg) {
|
|
220318
220705
|
const findings = [];
|
|
@@ -220341,8 +220728,24 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220341
220728
|
let epics = [];
|
|
220342
220729
|
let tasks = [];
|
|
220343
220730
|
let totalAc = 0;
|
|
220731
|
+
const state = waveConfigState(cfg);
|
|
220344
220732
|
block("config", () => {
|
|
220345
220733
|
if (cfg.loadedFrom === void 0) add("config.missing", null, "no se encontro workflow.config.json");
|
|
220734
|
+
const raw = state.raw;
|
|
220735
|
+
const version = typeof raw["version"] === "number" ? raw["version"] : state.version;
|
|
220736
|
+
for (const key of [
|
|
220737
|
+
"version",
|
|
220738
|
+
"layout",
|
|
220739
|
+
"waves",
|
|
220740
|
+
"thresholds",
|
|
220741
|
+
"vocabulary"
|
|
220742
|
+
]) if (raw[key] === void 0) add("config.missing_key", null, `falta la clave "${key}"`);
|
|
220743
|
+
if (version !== 1 && version !== 2) add("config.version_unknown", null, `version "${String(version)}" fuera de uno y dos: el gate no sabe leerla`);
|
|
220744
|
+
if (version === 2) {
|
|
220745
|
+
if (raw["wavesOpen"] === void 0) add("config.missing_key", null, "falta la clave \"wavesOpen\"");
|
|
220746
|
+
if (raw["vocabulary"] === void 0 || record$1(raw["vocabulary"])["units"] === void 0) add("config.missing_key", null, "falta la clave \"vocabulary.units\"");
|
|
220747
|
+
if (raw["falsifier"] === void 0) add("config.missing_key", null, "falta la clave \"falsifier\"");
|
|
220748
|
+
}
|
|
220346
220749
|
if (cfg.waves.length === 0) add("config.bad_waves", null, "waves debe ser un array no vacio");
|
|
220347
220750
|
if (vocabulary.verifyCommands.length === 0) add("config.bad_vocabulary", null, "vocabulary.verifyCommands vacio");
|
|
220348
220751
|
if (vocabulary.verifyPrefixes.length === 0) add("config.bad_vocabulary", null, "vocabulary.verifyPrefixes vacio");
|
|
@@ -220378,19 +220781,89 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220378
220781
|
}
|
|
220379
220782
|
}
|
|
220380
220783
|
});
|
|
220784
|
+
block("brief", () => {
|
|
220785
|
+
const templateFile = join(root, BRIEF_TEMPLATE$1);
|
|
220786
|
+
if (!fs.exists(templateFile)) return;
|
|
220787
|
+
const template = briefSections(fs.read(templateFile) ?? "");
|
|
220788
|
+
if (wavesDir === void 0 || !fs.isDirectory(wavesDir)) return;
|
|
220789
|
+
for (const wave of cfg.waves) {
|
|
220790
|
+
const match = waveDirs.find((name) => name === wave || name.startsWith(`${wave}-`));
|
|
220791
|
+
if (match === void 0) continue;
|
|
220792
|
+
const file = join(wavesDir, match, "00-brief.md");
|
|
220793
|
+
const text = fs.read(file);
|
|
220794
|
+
if (text === void 0) continue;
|
|
220795
|
+
const at = relative$1(root, file);
|
|
220796
|
+
const sections = briefSections(text);
|
|
220797
|
+
if (sections.length !== template.length) add("waves.brief_template_drift", at, `${sections.length} secciones frente a ${template.length} de ${BRIEF_TEMPLATE$1}: el brief ya no sigue la plantilla`);
|
|
220798
|
+
for (const [index, expected] of template.entries()) {
|
|
220799
|
+
const section = sections[index];
|
|
220800
|
+
if (section === void 0) continue;
|
|
220801
|
+
if (sectionKeyword(section.title) !== sectionKeyword(expected.title)) add("waves.brief_template_drift", at, `la seccion ${index + 1} se titula "${section.title}" y ${BRIEF_TEMPLATE$1} exige "${expected.title}"`);
|
|
220802
|
+
}
|
|
220803
|
+
for (const section of sections) if (section.body === "") add("waves.brief_empty_section", at, `la seccion "${section.title}" no tiene contenido`);
|
|
220804
|
+
}
|
|
220805
|
+
});
|
|
220381
220806
|
block("decision", () => {
|
|
220382
220807
|
const dir = wavesDir;
|
|
220383
220808
|
if (dir === void 0 || !fs.isDirectory(dir)) return;
|
|
220809
|
+
const axes = cfg.quorum.axes;
|
|
220810
|
+
const proposals = Array.from({ length: cfg.roles.proponents }, (_, index) => `P${index + 1}`);
|
|
220811
|
+
const judges = cfg.roles.judges;
|
|
220384
220812
|
for (const wave of cfg.waves) {
|
|
220385
220813
|
const match = waveDirs.find((name) => name === wave || name.startsWith(`${wave}-`));
|
|
220386
220814
|
if (match === void 0) continue;
|
|
220387
|
-
const
|
|
220815
|
+
const base = join(dir, match);
|
|
220816
|
+
const file = join(base, DECISION_FILE);
|
|
220388
220817
|
const text = fs.read(file);
|
|
220389
220818
|
if (text === void 0) continue;
|
|
220390
220819
|
const low = normalize$1(text);
|
|
220391
220820
|
const at = relative$1(root, file);
|
|
220392
|
-
|
|
220393
|
-
|
|
220821
|
+
const matrix = parseDecisionMatrix(text, {
|
|
220822
|
+
axes,
|
|
220823
|
+
proposals
|
|
220824
|
+
});
|
|
220825
|
+
for (const proposal of proposals) if (!matrix.presentProposals.includes(proposal)) add("waves.decision_missing_role", at, `no hay columna ${proposal} en la matriz de la ronda`);
|
|
220826
|
+
if (!matrix.present) add("waves.decision_without_quorum", at, "sin tabla de la matriz: la ronda no trae puntuaciones que auditar");
|
|
220827
|
+
else {
|
|
220828
|
+
for (const axis of axes) if (!matrix.axesFound.includes(axis)) add("waves.decision_missing_axis", at, `sin eje "${axis}" en la matriz`);
|
|
220829
|
+
for (const item of matrix.missing) add("waves.decision_matrix_incomplete", at, `eje "${item.axis}" · propuesta ${item.proposal}: celda vacia`);
|
|
220830
|
+
for (const proposal of proposals) {
|
|
220831
|
+
const declared = matrix.totals[proposal];
|
|
220832
|
+
const sum = decisionProposalSum(matrix, proposal);
|
|
220833
|
+
if (declared === void 0 || sum === void 0 || declared === sum) continue;
|
|
220834
|
+
add("waves.decision_total_mismatch", at, `${proposal}: total declarado ${declared} y recalculado ${sum} desde las celdas de la matriz`);
|
|
220835
|
+
}
|
|
220836
|
+
if (proposals.some((proposal) => matrix.medians[proposal] !== void 0)) {
|
|
220837
|
+
const verdictsDir = join(base, "04-verdicts");
|
|
220838
|
+
const recalc = decisionRecalculateMedians(Array.from({ length: judges }, (_, index) => {
|
|
220839
|
+
const name = `J${index + 1}.md`;
|
|
220840
|
+
return {
|
|
220841
|
+
file: `${relative$1(root, verdictsDir)}/${name}`,
|
|
220842
|
+
text: fs.read(join(verdictsDir, name)) ?? ""
|
|
220843
|
+
};
|
|
220844
|
+
}), {
|
|
220845
|
+
axes,
|
|
220846
|
+
proposals
|
|
220847
|
+
});
|
|
220848
|
+
for (const missing of recalc.missing) add("waves.decision_matrix_incomplete", missing, `sin tabla de ${axes.length} ejes por propuesta: no hay de donde recalcular la mediana`);
|
|
220849
|
+
if (recalc.missing.length === 0) {
|
|
220850
|
+
const citation = Array.from({ length: judges }, (_, index) => `04-verdicts/J${index + 1}.md`).join(", ");
|
|
220851
|
+
for (const proposal of proposals) {
|
|
220852
|
+
const declared = matrix.medians[proposal];
|
|
220853
|
+
const value = recalc.medians[proposal];
|
|
220854
|
+
if (declared === void 0 || value === void 0 || declared === value) continue;
|
|
220855
|
+
add("waves.decision_median_mismatch", at, `${proposal}: mediana declarada ${declared} y recalculada ${value} desde ${citation}`);
|
|
220856
|
+
}
|
|
220857
|
+
}
|
|
220858
|
+
}
|
|
220859
|
+
if (matrix.margins.length > 0) {
|
|
220860
|
+
const dissent = normalize$1(matrix.dissent ?? "");
|
|
220861
|
+
for (const row of matrix.margins) {
|
|
220862
|
+
if (row.margin >= 0 || dissent.includes(normalize$1(row.judge))) continue;
|
|
220863
|
+
add("waves.decision_undisclosed_dissent", at, `${row.judge}: margen ${row.margin} y no aparece en "## Disidencias"`);
|
|
220864
|
+
}
|
|
220865
|
+
}
|
|
220866
|
+
}
|
|
220394
220867
|
if (!/^#{1,3}\s+\d*\.?\s*disidencias/im.test(text)) add("waves.decision_without_dissent", at, "falta la seccion \"## Disidencias\"");
|
|
220395
220868
|
if (text.length < thresholds.minDecisionBytes) add("waves.decision_thin", at, `${text.length} B < ${thresholds.minDecisionBytes} B minimos`);
|
|
220396
220869
|
const numbers = text.match(/\b\d+(?:[.,]\d+)?\b/g)?.length ?? 0;
|
|
@@ -220479,10 +220952,16 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220479
220952
|
if (tasks.length < thresholds.minTasks) add("tasks.count", null, `${tasks.length} tasks < ${thresholds.minTasks} minimas`);
|
|
220480
220953
|
});
|
|
220481
220954
|
block("ac", () => {
|
|
220482
|
-
const vague = vocabulary.vagueWords.map((word) => normalize$1(word)).filter(Boolean)
|
|
220483
|
-
|
|
220955
|
+
const vague = vocabulary.vagueWords.map((word) => normalize$1(word)).filter(Boolean).map((word) => ({
|
|
220956
|
+
word,
|
|
220957
|
+
root: word.replace(/[aeiou]$/, "")
|
|
220958
|
+
})).filter((entry) => entry.root !== "");
|
|
220959
|
+
const units = asArray$1(record$1(state.raw["vocabulary"])["units"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
220960
|
+
const falsifierLexicon = record$1(state.raw["falsifier"]);
|
|
220961
|
+
const stateVerbs = asArray$1(falsifierLexicon["stateVerbs"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
220962
|
+
const stateObjects = asArray$1(falsifierLexicon["stateObjects"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
220484
220963
|
const withFalsifier = /* @__PURE__ */ new Set();
|
|
220485
|
-
const
|
|
220964
|
+
const openWaves = new Set(state.wavesOpen);
|
|
220486
220965
|
for (const task of tasks) {
|
|
220487
220966
|
const taskId = str$2(task["id"]);
|
|
220488
220967
|
for (const raw of asArray$1(task["ac"])) {
|
|
@@ -220502,31 +220981,67 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220502
220981
|
}
|
|
220503
220982
|
const metric = str$2(ac["metric"]);
|
|
220504
220983
|
if (metric !== "" && metric.length < thresholds.minMetricChars) add("ac.short_metric", at, `"metric" < ${thresholds.minMetricChars} caracteres`);
|
|
220505
|
-
const
|
|
220506
|
-
|
|
220507
|
-
|
|
220508
|
-
const
|
|
220509
|
-
if (
|
|
220984
|
+
const threshold = str$2(ac["threshold"]);
|
|
220985
|
+
if (threshold !== "" && !measurableThreshold(threshold, units)) add("ac.threshold_not_measurable", at, `"${threshold}" no compara ninguna magnitud: falta operador con numero, numero con unidad o conjunto enumerable`);
|
|
220986
|
+
const prose = normalize$1(`${str$2(ac["then"])} ${threshold} ${metric}`);
|
|
220987
|
+
const vagueHit = vague.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry.root)}[a-z]{0,10}\\b`).test(prose));
|
|
220988
|
+
if (vagueHit !== void 0) {
|
|
220989
|
+
const matched = new RegExp(`\\b${escapeRegExp$1(vagueHit.root)}[a-z]{0,10}\\b`).exec(prose)?.[0] ?? vagueHit.root;
|
|
220990
|
+
add("ac.vague_language", at, `"${matched}" contiene la raiz "${vagueHit.root}" de "${vagueHit.word}": no es medible`);
|
|
220991
|
+
}
|
|
220510
220992
|
const verify = str$2(ac["verify"]).trim();
|
|
220511
220993
|
if (verify !== "") {
|
|
220512
220994
|
const command = verify.split(/\s+/)[0] ?? "";
|
|
220513
220995
|
if (!vocabulary.verifyCommands.includes(command)) add("ac.verify_not_command", at, `"${command}" no es un comando de la lista permitida`);
|
|
220514
220996
|
else {
|
|
220515
|
-
|
|
220516
|
-
|
|
220517
|
-
|
|
220518
|
-
|
|
220997
|
+
let argv;
|
|
220998
|
+
try {
|
|
220999
|
+
argv = splitCommand(verify);
|
|
221000
|
+
} catch (error) {
|
|
221001
|
+
add("ac.verify_command_unsafe", at, error instanceof Error ? error.message : String(error));
|
|
221002
|
+
}
|
|
221003
|
+
if (argv !== void 0) {
|
|
221004
|
+
let escaped;
|
|
221005
|
+
for (const token of argv) {
|
|
221006
|
+
if (token.startsWith("-") || !token.includes("/")) continue;
|
|
221007
|
+
try {
|
|
221008
|
+
containedPath(root, token);
|
|
221009
|
+
} catch {
|
|
221010
|
+
escaped = token;
|
|
221011
|
+
break;
|
|
221012
|
+
}
|
|
221013
|
+
}
|
|
221014
|
+
if (escaped !== void 0) add("ac.verify_command_unsafe", at, `el token "${escaped}" escapa de la raiz del paquete`);
|
|
221015
|
+
else {
|
|
221016
|
+
const token = argv.slice(1).find((item) => !item.startsWith("-") && item.includes("/"));
|
|
221017
|
+
if (token === void 0) add("ac.verify_outside_test_plan", at, "el comando no apunta a ningun fichero o directorio verificable");
|
|
221018
|
+
else {
|
|
221019
|
+
const target = token.replace(/^\.\//, "");
|
|
221020
|
+
if (!vocabulary.verifyPrefixes.some((prefix) => target.startsWith(prefix))) add("ac.verify_outside_test_plan", at, `"${target}" fuera del test plan declarado`);
|
|
221021
|
+
else if (state.version >= 2 && !openWaves.has(str$2(task["wave"])) && !fs.exists(join(root, target))) add("ac.verify_target_missing", at, `el destino "${target}" no existe bajo la raiz del paquete`);
|
|
221022
|
+
const destination = join(root, target);
|
|
221023
|
+
const isTest = /(^|\/)test\//.test(target) || /\.test\./.test(target);
|
|
221024
|
+
const exempt = /(^|\/)scripts\//.test(target);
|
|
221025
|
+
if (isTest && !exempt && fs.exists(destination) && fs.isDirectory(destination) === false) {
|
|
221026
|
+
if ((fs.read(destination) ?? "").match(ASSERTION) === null) add("ac.verify_stub", at, `el destino "${target}" no tiene ninguna asercion: el verify no mide nada`);
|
|
221027
|
+
}
|
|
221028
|
+
}
|
|
221029
|
+
}
|
|
221030
|
+
}
|
|
220519
221031
|
}
|
|
220520
221032
|
}
|
|
220521
221033
|
const falsifier = record$1(ac["falsifier"]);
|
|
220522
221034
|
if (Object.keys(falsifier).length > 0) {
|
|
220523
221035
|
const mutation = str$2(falsifier["mutation"]);
|
|
220524
221036
|
const expect = str$2(falsifier["expect"]);
|
|
220525
|
-
const script = str$2(falsifier["script"]);
|
|
220526
221037
|
if (mutation.length < thresholds.minFieldChars) add("ac.falsifier_thin", at, "falsifier.mutation insuficiente");
|
|
220527
221038
|
else if (expect.length < thresholds.minFieldChars) add("ac.falsifier_thin", at, "falsifier.expect insuficiente");
|
|
220528
|
-
else if (script === "" && isDestructive(mutation)) add("ac.falsifier_not_reversible", at, `"${mutation}" necesita falsifier.script con apply y restore`);
|
|
220529
221039
|
else withFalsifier.add(taskId);
|
|
221040
|
+
const normalizedMutation = normalize$1(mutation);
|
|
221041
|
+
const verb = stateVerbs.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry)}[a-z]{0,4}\\b`).test(normalizedMutation));
|
|
221042
|
+
const object = stateObjects.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry)}s?\\b`).test(normalizedMutation));
|
|
221043
|
+
const reversible = str$2(falsifier["script"]).trim() !== "" || str$2(falsifier["restore"]).trim() !== "";
|
|
221044
|
+
if (verb !== void 0 && object !== void 0 && !reversible) add("ac.falsifier_not_reversible", at, `la mutacion "${verb} ... ${object}" toca estado sin falsifier.script ni falsifier.restore`);
|
|
220530
221045
|
}
|
|
220531
221046
|
}
|
|
220532
221047
|
}
|
|
@@ -220572,6 +221087,19 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220572
221087
|
}
|
|
220573
221088
|
});
|
|
220574
221089
|
block("hygiene", () => {
|
|
221090
|
+
const wavesDir = join(root, cfg.layout.waves);
|
|
221091
|
+
for (const wave of cfg.waves) {
|
|
221092
|
+
const dir = fs.list(wavesDir).find((entry) => entry === wave || entry.startsWith(`${wave}-`));
|
|
221093
|
+
if (dir === void 0) continue;
|
|
221094
|
+
const contracted = contractedSeats(fs, join(wavesDir, dir, WAVE_CONTRACTS_FILE));
|
|
221095
|
+
if (contracted === void 0) continue;
|
|
221096
|
+
for (const round of WAVE_ROUNDS) for (const role of waveRoundSeats(cfg.roles, round)) {
|
|
221097
|
+
const path = `${cfg.layout.waves}/${dir}/${WAVE_ROUND_DIRS[round]}/${role}.md`;
|
|
221098
|
+
if (!fs.exists(join(root, path))) continue;
|
|
221099
|
+
if (contracted.some((seat) => seat.round === round && seat.role === role)) continue;
|
|
221100
|
+
add("contracts.uncontracted", path, `el asiento ${role} de ${round} entrego sin contrato de WaveContract`);
|
|
221101
|
+
}
|
|
221102
|
+
}
|
|
220575
221103
|
const secrets = cfg.secrets.filter((secret) => secret.length >= 6);
|
|
220576
221104
|
if (secrets.length === 0) return;
|
|
220577
221105
|
const files = [...walk(fs, join(root, cfg.layout.waves), (path) => /\.(md|json|txt)$/.test(path)), ...walk(fs, join(root, cfg.layout.backlog), (path) => /\.(md|json|txt)$/.test(path))];
|
|
@@ -220588,14 +221116,18 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220588
221116
|
waves: cfg.waves.length,
|
|
220589
221117
|
epics: epics.length,
|
|
220590
221118
|
tasks: tasks.length,
|
|
220591
|
-
ac: totalAc
|
|
221119
|
+
ac: totalAc,
|
|
221120
|
+
notRun: NOT_RUN_BLOCKS
|
|
220592
221121
|
}
|
|
220593
221122
|
};
|
|
220594
221123
|
}
|
|
220595
|
-
var DECISION_FILE, AC_FIELDS, normalize$1, relative$1;
|
|
221124
|
+
var DECISION_FILE, BRIEF_TEMPLATE$1, AC_FIELDS, OPERATOR_WITH_NUMBER, EXACT_VALUE, ASSERTION, escapeRegExp$1, NOT_RUN_BLOCKS, normalize$1, relative$1, DECISION_SEPARATOR, DECISION_PROPOSAL, DECISION_LEADING_NUMBER, DECISION_JUDGE, DECISION_SIGNED_MARGIN;
|
|
220596
221125
|
var init_checks = __esmMin((() => {
|
|
220597
221126
|
init_config$6();
|
|
221127
|
+
init_seats();
|
|
221128
|
+
init_runner();
|
|
220598
221129
|
DECISION_FILE = "06-DECISION.md";
|
|
221130
|
+
BRIEF_TEMPLATE$1 = "workflow/templates/brief.md";
|
|
220599
221131
|
AC_FIELDS = [
|
|
220600
221132
|
"id",
|
|
220601
221133
|
"given",
|
|
@@ -220606,8 +221138,24 @@ var init_checks = __esmMin((() => {
|
|
|
220606
221138
|
"verify",
|
|
220607
221139
|
"falsifier"
|
|
220608
221140
|
];
|
|
221141
|
+
OPERATOR_WITH_NUMBER = /[=<>≥≤]\s*\d|\b(?:mayor|menor|igual|al menos|como maximo|como minimo)\b[^0-9]{0,20}\d/;
|
|
221142
|
+
EXACT_VALUE = /\b\d+(?:[.,]\d+)?\s+(?:exacto|exacta|exactos|exactas|fijo|fija|justo|justa)\b/;
|
|
221143
|
+
ASSERTION = /\bassert\b|\bexpect\s*\(|\bit\s*\(|\btest\s*\(|\bfailures\b|process\.exit\s*\(\s*(?!0\b)/g;
|
|
221144
|
+
escapeRegExp$1 = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
221145
|
+
NOT_RUN_BLOCKS = [{
|
|
221146
|
+
block: "regression",
|
|
221147
|
+
closedBy: "oracle"
|
|
221148
|
+
}, {
|
|
221149
|
+
block: "schemas",
|
|
221150
|
+
closedBy: "oracle"
|
|
221151
|
+
}];
|
|
220609
221152
|
normalize$1 = (value) => value.normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").toLowerCase();
|
|
220610
221153
|
relative$1 = (root, path) => path.startsWith(root) ? path.slice(root.length).replaceAll("\\", "/").replace(/^\/+/, "") : path;
|
|
221154
|
+
DECISION_SEPARATOR = /^:?-{2,}:?$/;
|
|
221155
|
+
DECISION_PROPOSAL = /^p\d+$/;
|
|
221156
|
+
DECISION_LEADING_NUMBER = /^[+-]?\d+(?:[.,]\d+)?/;
|
|
221157
|
+
DECISION_JUDGE = /^J\d+$/;
|
|
221158
|
+
DECISION_SIGNED_MARGIN = /^([+-]?\d+(?:[.,]\d+)?)$/;
|
|
220611
221159
|
}));
|
|
220612
221160
|
// ../../packages/agent-core-v2/src/features/wave/tools/gate/gateRunner.ts
|
|
220613
221161
|
function runWaveGateForRoot(input) {
|
|
@@ -220629,6 +221177,7 @@ function runWaveGateForRoot(input) {
|
|
|
220629
221177
|
};
|
|
220630
221178
|
const lines = [`GATE — ${report.ok ? "verde" : "con hallazgos"}`, ""];
|
|
220631
221179
|
for (const block of report.blocks) lines.push(`${block.ok ? "OK " : "FAIL"} ${block.name}`);
|
|
221180
|
+
for (const entry of report.summary.notRun) lines.push(`NO EJECUTADO ${entry.block} — cerrado por ${entry.closedBy}`);
|
|
220632
221181
|
if (report.findings.length > 0) {
|
|
220633
221182
|
lines.push("", `PENDIENTE: ${report.findings.length} hallazgo(s)`, "");
|
|
220634
221183
|
for (const finding of report.findings) lines.push(` - ${finding.code}${finding.path === null ? "" : ` ${finding.path}`} — ${finding.message}`);
|
|
@@ -220680,175 +221229,328 @@ var init_gateTool = __esmMin((() => {
|
|
|
220680
221229
|
};
|
|
220681
221230
|
WaveGateTool = __decorate([__decorateParam(0, ISessionContext)], WaveGateTool);
|
|
220682
221231
|
}));
|
|
220683
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/
|
|
220684
|
-
var
|
|
220685
|
-
var
|
|
221232
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/open/open.ts
|
|
221233
|
+
var WaveOpenToolInputSchema, IWaveOpenTool;
|
|
221234
|
+
var init_open$1 = __esmMin((() => {
|
|
220686
221235
|
init_zod$1();
|
|
220687
221236
|
init_instantiation();
|
|
220688
|
-
|
|
220689
|
-
|
|
221237
|
+
WaveOpenToolInputSchema = object$1({
|
|
221238
|
+
name: string().min(2),
|
|
221239
|
+
id: string().optional(),
|
|
220690
221240
|
root: string().optional()
|
|
220691
221241
|
}).strict();
|
|
220692
|
-
|
|
221242
|
+
IWaveOpenTool = createDecorator("waveOpenTool");
|
|
220693
221243
|
}));
|
|
220694
|
-
// ../../packages/agent-core-v2/src/features/wave/
|
|
220695
|
-
function
|
|
220696
|
-
const
|
|
220697
|
-
|
|
220698
|
-
|
|
220699
|
-
|
|
220700
|
-
|
|
220701
|
-
if (char === quote) quote = void 0;
|
|
220702
|
-
else current += char;
|
|
220703
|
-
continue;
|
|
220704
|
-
}
|
|
220705
|
-
if (char === "\"" || char === "'") {
|
|
220706
|
-
quote = char;
|
|
220707
|
-
continue;
|
|
220708
|
-
}
|
|
220709
|
-
if (SHELL_METACHARACTERS.has(char)) throw new Error(`metacaracter de shell prohibido en: ${command}`);
|
|
220710
|
-
if (char === " " || char === " ") {
|
|
220711
|
-
if (current !== "") {
|
|
220712
|
-
tokens.push(current);
|
|
220713
|
-
current = "";
|
|
220714
|
-
}
|
|
220715
|
-
continue;
|
|
220716
|
-
}
|
|
220717
|
-
current += char;
|
|
220718
|
-
}
|
|
220719
|
-
if (quote !== void 0) throw new Error(`comillas sin cerrar en: ${command}`);
|
|
220720
|
-
if (current !== "") tokens.push(current);
|
|
220721
|
-
if (tokens.length === 0) throw new Error("comando vacio");
|
|
220722
|
-
return tokens;
|
|
221244
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/open/openRunner.ts
|
|
221245
|
+
function briefTemplate(root) {
|
|
221246
|
+
const fs = nodeWaveFs;
|
|
221247
|
+
const local = join(root, BRIEF_TEMPLATE);
|
|
221248
|
+
if (fs.exists(local)) return { file: local };
|
|
221249
|
+
if (fs.isDirectory(join(root, "workflow"))) return { missing: BRIEF_TEMPLATE };
|
|
221250
|
+
return fs.exists(BUNDLED_BRIEF_TEMPLATE) ? { file: BUNDLED_BRIEF_TEMPLATE } : { missing: BRIEF_TEMPLATE };
|
|
220723
221251
|
}
|
|
220724
|
-
function
|
|
220725
|
-
|
|
220726
|
-
|
|
220727
|
-
|
|
220728
|
-
containedPath(root, token);
|
|
220729
|
-
}
|
|
221252
|
+
function nextEpic(backlogDir) {
|
|
221253
|
+
const numbers = asArray$2(asRecord$2(readJson$2(nodeWaveFs, join(backlogDir, "epics.json")) ?? {})["epics"]).map((epic) => /^E(\d{2,})$/.exec(String(asRecord$2(epic)["id"]))?.[1]).filter((value) => value !== void 0).map(Number);
|
|
221254
|
+
const next = numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
221255
|
+
return `E${String(next).padStart(2, "0")}`;
|
|
220730
221256
|
}
|
|
220731
|
-
function
|
|
220732
|
-
|
|
221257
|
+
function slugify(name) {
|
|
221258
|
+
return name.normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "");
|
|
221259
|
+
}
|
|
221260
|
+
function runWaveOpenForRoot(input) {
|
|
221261
|
+
const fs = nodeWaveFs;
|
|
221262
|
+
const configFile = join(input.root, "workflow.config.json");
|
|
221263
|
+
const rawConfig = readJson$2(fs, configFile);
|
|
221264
|
+
if (rawConfig === void 0) return {
|
|
221265
|
+
output: `no hay workflow.config.json en ${input.root}`,
|
|
221266
|
+
isError: true
|
|
221267
|
+
};
|
|
221268
|
+
const layout = asRecord$2(asRecord$2(rawConfig)["layout"]);
|
|
221269
|
+
const wavesRel = typeof layout["waves"] === "string" ? layout["waves"] : "design/waves";
|
|
221270
|
+
const backlogRel = typeof layout["backlog"] === "string" ? layout["backlog"] : "backlog";
|
|
221271
|
+
const minimum = makeWaveConfig(rawConfig).thresholds.minBriefSections;
|
|
221272
|
+
let wavesDir;
|
|
221273
|
+
let backlogDir;
|
|
220733
221274
|
try {
|
|
220734
|
-
|
|
220735
|
-
|
|
220736
|
-
const allowed = options.allowBinaries.map((item) => item.replace(/\.exe$/i, ""));
|
|
220737
|
-
if (!allowed.includes(binary)) throw new Error(`binario no permitido: ${binary} (permitidos: ${allowed.join(", ")})`);
|
|
220738
|
-
containPaths(argv, options.root);
|
|
221275
|
+
wavesDir = containedPath(input.root, wavesRel);
|
|
221276
|
+
backlogDir = containedPath(input.root, backlogRel);
|
|
220739
221277
|
} catch (error) {
|
|
220740
221278
|
return {
|
|
220741
|
-
|
|
220742
|
-
|
|
220743
|
-
rejected: true
|
|
221279
|
+
output: error instanceof Error ? error.message : String(error),
|
|
221280
|
+
isError: true
|
|
220744
221281
|
};
|
|
220745
221282
|
}
|
|
220746
|
-
const
|
|
220747
|
-
|
|
220748
|
-
|
|
220749
|
-
|
|
220750
|
-
stdio: "pipe",
|
|
220751
|
-
shell: false
|
|
220752
|
-
});
|
|
220753
|
-
const output = `${result.stdout ?? ""}${result.stderr ?? ""}${result.error === void 0 ? "" : result.error.message}`.replaceAll(/\s+/g, " ").trim().slice(0, 300);
|
|
220754
|
-
if (result.error !== void 0) return {
|
|
220755
|
-
ok: false,
|
|
220756
|
-
output: `no se pudo ejecutar: ${output}`,
|
|
220757
|
-
rejected: false
|
|
221283
|
+
const template = briefTemplate(input.root);
|
|
221284
|
+
if (template.file === void 0) return {
|
|
221285
|
+
output: `falta ${template.missing ?? BRIEF_TEMPLATE}: no se genera un brief sin la plantilla unica`,
|
|
221286
|
+
isError: true
|
|
220758
221287
|
};
|
|
220759
|
-
|
|
220760
|
-
|
|
220761
|
-
output
|
|
220762
|
-
|
|
221288
|
+
const source = fs.read(template.file);
|
|
221289
|
+
if (source === void 0) return {
|
|
221290
|
+
output: `no se pudo leer ${template.file}`,
|
|
221291
|
+
isError: true
|
|
220763
221292
|
};
|
|
220764
|
-
|
|
220765
|
-
|
|
220766
|
-
|
|
220767
|
-
|
|
220768
|
-
|
|
220769
|
-
detail: "sin falsifier.script: el AC queda declarado y cuenta como FALLO"
|
|
221293
|
+
const existing = fs.list(wavesDir).filter((name) => fs.isDirectory(join(wavesDir, name))).map((name) => Number(/^W(\d+)/.exec(name)?.[1] ?? NaN)).filter((value) => !Number.isNaN(value));
|
|
221294
|
+
const next = input.id ?? `W${existing.length > 0 ? Math.max(...existing) + 1 : 0}`;
|
|
221295
|
+
if (!/^W\d{1,2}$/.test(next)) return {
|
|
221296
|
+
output: `id de oleada invalido "${next}"`,
|
|
221297
|
+
isError: true
|
|
220770
221298
|
};
|
|
220771
|
-
const
|
|
220772
|
-
if (
|
|
220773
|
-
|
|
220774
|
-
|
|
221299
|
+
const slug = slugify(input.name);
|
|
221300
|
+
if (slug === "") return {
|
|
221301
|
+
output: "el nombre de la oleada queda vacio al normalizarlo",
|
|
221302
|
+
isError: true
|
|
220775
221303
|
};
|
|
220776
|
-
if (
|
|
220777
|
-
|
|
220778
|
-
|
|
221304
|
+
if (fs.list(wavesDir).some((name) => name === next || name.startsWith(`${next}-`))) return {
|
|
221305
|
+
output: `la oleada ${next} ya existe`,
|
|
221306
|
+
isError: true
|
|
220779
221307
|
};
|
|
220780
|
-
const
|
|
220781
|
-
const
|
|
220782
|
-
const
|
|
220783
|
-
|
|
220784
|
-
|
|
220785
|
-
|
|
221308
|
+
const dir = join(wavesDir, `${next}-${slug}`);
|
|
221309
|
+
const brief = source.replaceAll("{{WAVE}}", next).replaceAll("{{NAME}}", slug).replaceAll("{{NEXT_EPIC}}", nextEpic(backlogDir));
|
|
221310
|
+
for (const sub of SUBDIRS) fs.mkdir(join(dir, sub));
|
|
221311
|
+
fs.write(join(dir, "00-brief.md"), brief);
|
|
221312
|
+
const declared = asArray$2(asRecord$2(rawConfig)["waves"]).map(String);
|
|
221313
|
+
if (!declared.includes(next)) writeJson(fs, configFile, {
|
|
221314
|
+
...asRecord$2(rawConfig),
|
|
221315
|
+
waves: [...declared, next].toSorted()
|
|
221316
|
+
});
|
|
221317
|
+
return { output: [
|
|
221318
|
+
`oleada creada: ${next}-${slug}`,
|
|
221319
|
+
` brief: ${wavesRel}/${next}-${slug}/00-brief.md (rellena las ${minimum} secciones antes de lanzar asientos)`,
|
|
221320
|
+
` config: ${next} declarada en workflow.config.json (el gate la exige desde ahora)`
|
|
221321
|
+
].join("\n") };
|
|
221322
|
+
}
|
|
221323
|
+
var SUBDIRS, BRIEF_TEMPLATE, BUNDLED_BRIEF_TEMPLATE;
|
|
221324
|
+
var init_openRunner = __esmMin((() => {
|
|
221325
|
+
init_config$6();
|
|
221326
|
+
init_fsJson();
|
|
221327
|
+
init_nodeFs();
|
|
221328
|
+
SUBDIRS = [
|
|
221329
|
+
"01-proposals",
|
|
221330
|
+
"02-defenses",
|
|
221331
|
+
"03-attacks",
|
|
221332
|
+
"04-verdicts",
|
|
221333
|
+
"05-refined"
|
|
221334
|
+
];
|
|
221335
|
+
BRIEF_TEMPLATE = "workflow/templates/brief.md";
|
|
221336
|
+
BUNDLED_BRIEF_TEMPLATE = resolve(import.meta.dirname, "../../../../../../../workflow/templates/brief.md");
|
|
221337
|
+
}));
|
|
221338
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/open/open.md?raw
|
|
221339
|
+
var open_default;
|
|
221340
|
+
var init_open = __esmMin((() => {
|
|
221341
|
+
open_default = "Open a wave: create its artifact tree and a brief skeleton, and declare the wave in `workflow.config.json`.\n\nThe brief starts with the seven mandatory sections and nothing else — a brief that already contains the answer makes the twelve seats theatre. Fill it before launching any seat; the gate rejects a brief with fewer than seven sections.\n\nOpening a wave also declares it in the config, so the package gate will require its artifacts from then on.\n";
|
|
221342
|
+
}));
|
|
221343
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/open/openTool.ts
|
|
221344
|
+
var WaveOpenTool;
|
|
221345
|
+
var init_openTool = __esmMin((() => {
|
|
221346
|
+
init_sessionContext();
|
|
221347
|
+
init_input_schema();
|
|
221348
|
+
init_open$1();
|
|
221349
|
+
init_openRunner();
|
|
221350
|
+
init_open();
|
|
221351
|
+
init_decorateParam();
|
|
221352
|
+
init_decorate();
|
|
221353
|
+
WaveOpenTool = class WaveOpenTool {
|
|
221354
|
+
sessionContext;
|
|
221355
|
+
name = "WaveOpen";
|
|
221356
|
+
description = open_default;
|
|
221357
|
+
parameters = toInputJsonSchema(WaveOpenToolInputSchema);
|
|
221358
|
+
constructor(sessionContext) {
|
|
221359
|
+
this.sessionContext = sessionContext;
|
|
221360
|
+
}
|
|
221361
|
+
resolveExecution(args) {
|
|
221362
|
+
return {
|
|
221363
|
+
description: `Opening wave ${args.name}`,
|
|
221364
|
+
approvalRule: this.name,
|
|
221365
|
+
execute: () => Promise.resolve(runWaveOpenForRoot({
|
|
221366
|
+
root: args.root ?? this.sessionContext.cwd,
|
|
221367
|
+
name: args.name,
|
|
221368
|
+
id: args.id
|
|
221369
|
+
}))
|
|
221370
|
+
};
|
|
221371
|
+
}
|
|
220786
221372
|
};
|
|
220787
|
-
|
|
220788
|
-
|
|
220789
|
-
|
|
221373
|
+
WaveOpenTool = __decorate([__decorateParam(0, ISessionContext)], WaveOpenTool);
|
|
221374
|
+
}));
|
|
221375
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submit.ts
|
|
221376
|
+
var WaveSubmitToolInputSchema, IWaveSubmitTool;
|
|
221377
|
+
var init_submit$1 = __esmMin((() => {
|
|
221378
|
+
init_zod$1();
|
|
221379
|
+
init_instantiation();
|
|
221380
|
+
WaveSubmitToolInputSchema = object$1({
|
|
221381
|
+
wave: string().min(2),
|
|
221382
|
+
round: _enum([
|
|
221383
|
+
"propose",
|
|
221384
|
+
"defend",
|
|
221385
|
+
"attack",
|
|
221386
|
+
"judge",
|
|
221387
|
+
"refine",
|
|
221388
|
+
"audit"
|
|
221389
|
+
]),
|
|
221390
|
+
role: string().min(2),
|
|
221391
|
+
artifact: string().min(1),
|
|
221392
|
+
ticket: string().optional(),
|
|
221393
|
+
reason: string().optional(),
|
|
221394
|
+
replace: boolean$1().optional(),
|
|
221395
|
+
root: string().optional()
|
|
221396
|
+
}).strict();
|
|
221397
|
+
IWaveSubmitTool = createDecorator("waveSubmitTool");
|
|
221398
|
+
}));
|
|
221399
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitRunner.ts
|
|
221400
|
+
function findWaveDir(root, wavesRel, wave) {
|
|
221401
|
+
const fs = nodeWaveFs;
|
|
221402
|
+
const wavesDir = containedPath(root, wavesRel);
|
|
221403
|
+
const name = fs.list(wavesDir).filter((entry) => fs.isDirectory(join(wavesDir, entry))).find((entry) => entry === wave || entry.startsWith(`${wave}-`));
|
|
221404
|
+
return name === void 0 ? void 0 : join(wavesDir, name);
|
|
221405
|
+
}
|
|
221406
|
+
function runWaveSubmitForRoot(input) {
|
|
221407
|
+
const fs = nodeWaveFs;
|
|
221408
|
+
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
221409
|
+
if (rawConfig === void 0) return {
|
|
221410
|
+
output: `no hay workflow.config.json en ${input.root}`,
|
|
221411
|
+
isError: true
|
|
220790
221412
|
};
|
|
220791
|
-
|
|
220792
|
-
|
|
220793
|
-
|
|
221413
|
+
const config = makeWaveConfig(rawConfig);
|
|
221414
|
+
const wavesRel = config.layout.waves;
|
|
221415
|
+
const seats = waveRoundSeats(config.roles, input.round);
|
|
221416
|
+
if (!seats.includes(input.role)) return {
|
|
221417
|
+
output: `seats.unknown_seat: el rol "${input.role}" no pertenece a la ronda ${input.round} (esperado ${seats.join(", ")})`,
|
|
221418
|
+
isError: true
|
|
220794
221419
|
};
|
|
220795
|
-
|
|
220796
|
-
|
|
220797
|
-
|
|
221420
|
+
let base;
|
|
221421
|
+
try {
|
|
221422
|
+
base = findWaveDir(input.root, wavesRel, input.wave);
|
|
221423
|
+
} catch (error) {
|
|
221424
|
+
return {
|
|
221425
|
+
output: error instanceof Error ? error.message : String(error),
|
|
221426
|
+
isError: true
|
|
221427
|
+
};
|
|
221428
|
+
}
|
|
221429
|
+
if (base === void 0) return {
|
|
221430
|
+
output: `no existe la oleada ${input.wave} en ${wavesRel}`,
|
|
221431
|
+
isError: true
|
|
220798
221432
|
};
|
|
220799
|
-
|
|
220800
|
-
|
|
220801
|
-
|
|
220802
|
-
|
|
220803
|
-
|
|
220804
|
-
const task = asRecord$2(readJson$2(fs, file));
|
|
220805
|
-
const runOptions = {
|
|
220806
|
-
root,
|
|
220807
|
-
allowBinaries: cfg.vocabulary.verifyCommands,
|
|
220808
|
-
cwd: options?.cwd,
|
|
220809
|
-
timeoutMs: options?.timeoutMs
|
|
221433
|
+
const dirName = WAVE_ROUND_DIRS[input.round];
|
|
221434
|
+
const dir = join(base, dirName);
|
|
221435
|
+
if (!fs.isDirectory(dir)) return {
|
|
221436
|
+
output: `falta el directorio ${dirName} en la oleada ${input.wave}`,
|
|
221437
|
+
isError: true
|
|
220810
221438
|
};
|
|
220811
|
-
const
|
|
220812
|
-
|
|
220813
|
-
|
|
220814
|
-
|
|
220815
|
-
|
|
220816
|
-
|
|
220817
|
-
|
|
220818
|
-
|
|
220819
|
-
|
|
220820
|
-
|
|
220821
|
-
|
|
220822
|
-
|
|
220823
|
-
|
|
220824
|
-
|
|
220825
|
-
|
|
221439
|
+
const seatsDir = join(base, WAVE_SEATS_DIR);
|
|
221440
|
+
if (fs.isDirectory(seatsDir) && fs.list(seatsDir).length > 0) {
|
|
221441
|
+
const presented = (input.ticket ?? "").trim();
|
|
221442
|
+
if (presented === "") return {
|
|
221443
|
+
output: `seats.foreign_replace: el asiento ${input.role} no presento el ticket que emitio la ronda`,
|
|
221444
|
+
isError: true
|
|
221445
|
+
};
|
|
221446
|
+
const stored = (fs.read(join(seatsDir, input.role)) ?? "").trim();
|
|
221447
|
+
if (stored === "" || stored !== seatTicketHash(presented)) return {
|
|
221448
|
+
output: `seats.foreign_replace: el ticket presentado no es el del asiento ${input.role}`,
|
|
221449
|
+
isError: true
|
|
221450
|
+
};
|
|
221451
|
+
if (input.replace === true && (input.reason ?? "").trim() === "") return {
|
|
221452
|
+
output: `seats.replace_without_reason: reescribir el artefacto del asiento ${input.role} exige un motivo no vacio`,
|
|
221453
|
+
isError: true
|
|
221454
|
+
};
|
|
220826
221455
|
}
|
|
220827
|
-
|
|
220828
|
-
|
|
220829
|
-
|
|
220830
|
-
|
|
220831
|
-
ok: acs.length > 0 && acs.every((ac) => ac.ok)
|
|
221456
|
+
const file = join(dir, `${input.role}.md`);
|
|
221457
|
+
if (fs.exists(file) && input.replace !== true) return {
|
|
221458
|
+
output: `el asiento ${input.role} ya entrego su artefacto; un asiento escribe una vez (usa replace solo para relanzar un fallo)`,
|
|
221459
|
+
isError: true
|
|
220832
221460
|
};
|
|
221461
|
+
if (input.artifact.trim() === "") return {
|
|
221462
|
+
output: "el artefacto esta vacio: un asiento que no escribe, fallo",
|
|
221463
|
+
isError: true
|
|
221464
|
+
};
|
|
221465
|
+
fs.write(file, input.artifact.endsWith("\n") ? input.artifact : `${input.artifact}\n`);
|
|
221466
|
+
return { output: `escrito ${wavesRel}/${base.split("/").pop()}/${dirName}/${input.role}.md` };
|
|
220833
221467
|
}
|
|
220834
|
-
var
|
|
220835
|
-
var init_runner = __esmMin((() => {
|
|
221468
|
+
var init_submitRunner = __esmMin((() => {
|
|
220836
221469
|
init_config$6();
|
|
220837
221470
|
init_fsJson();
|
|
220838
|
-
|
|
220839
|
-
|
|
220840
|
-
|
|
220841
|
-
|
|
220842
|
-
|
|
220843
|
-
|
|
220844
|
-
|
|
220845
|
-
|
|
220846
|
-
|
|
220847
|
-
|
|
220848
|
-
|
|
220849
|
-
|
|
221471
|
+
init_nodeFs();
|
|
221472
|
+
init_seats();
|
|
221473
|
+
}));
|
|
221474
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submit.md?raw
|
|
221475
|
+
var submit_default;
|
|
221476
|
+
var init_submit = __esmMin((() => {
|
|
221477
|
+
submit_default = "Deliver the artifact for your seat. This is the only way a seat writes: the tool binds the role to its slot and refuses anything else.\n\nRole and round must match — `propose` accepts P1..Pn, `defend` D1..Dn, `attack` A1..An, `judge` J1..Jn, `refine` R1, `audit` R2..Rn. A seat writes once; use `replace` only to relaunch a failed seat after its artifact was already written.\n\nPass the `ticket` the round gave you: the tool hashes it and compares it with the sha256 the round left in `design/waves/<W>/.seats/<role>`. A missing ticket, or the ticket of another seat, is refused as `seats.foreign_replace`. The ticket is capacity, not identity (capacidad, no identidad): it proves the orchestrator issued this seat, it does not say who wrote the artifact. `replace` also needs a non-empty `reason`, or the tool refuses it as `seats.replace_without_reason`: a silent overwrite is the substitution this tool exists to prevent.\n\nPass the artifact as the text/JSON body. An empty artifact is rejected: a seat that did not write has failed, and the round must be relaunched rather than summarized by the orchestrator.\n";
|
|
221478
|
+
}));
|
|
221479
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitTool.ts
|
|
221480
|
+
var WaveSubmitTool;
|
|
221481
|
+
var init_submitTool = __esmMin((() => {
|
|
221482
|
+
init_sessionContext();
|
|
221483
|
+
init_input_schema();
|
|
221484
|
+
init_submit$1();
|
|
221485
|
+
init_submitRunner();
|
|
221486
|
+
init_submit();
|
|
221487
|
+
init_decorateParam();
|
|
221488
|
+
init_decorate();
|
|
221489
|
+
WaveSubmitTool = class WaveSubmitTool {
|
|
221490
|
+
sessionContext;
|
|
221491
|
+
name = "WaveSubmit";
|
|
221492
|
+
description = submit_default;
|
|
221493
|
+
parameters = toInputJsonSchema(WaveSubmitToolInputSchema);
|
|
221494
|
+
constructor(sessionContext) {
|
|
221495
|
+
this.sessionContext = sessionContext;
|
|
221496
|
+
}
|
|
221497
|
+
resolveExecution(args) {
|
|
221498
|
+
return {
|
|
221499
|
+
description: `Submitting ${args.role}`,
|
|
221500
|
+
approvalRule: this.name,
|
|
221501
|
+
execute: () => Promise.resolve(runWaveSubmitForRoot({
|
|
221502
|
+
root: args.root ?? this.sessionContext.cwd,
|
|
221503
|
+
wave: args.wave,
|
|
221504
|
+
round: args.round,
|
|
221505
|
+
role: args.role,
|
|
221506
|
+
artifact: args.artifact,
|
|
221507
|
+
ticket: args.ticket,
|
|
221508
|
+
reason: args.reason,
|
|
221509
|
+
replace: args.replace
|
|
221510
|
+
}))
|
|
221511
|
+
};
|
|
221512
|
+
}
|
|
221513
|
+
};
|
|
221514
|
+
WaveSubmitTool = __decorate([__decorateParam(0, ISessionContext)], WaveSubmitTool);
|
|
221515
|
+
}));
|
|
221516
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verify.ts
|
|
221517
|
+
var WaveVerifyToolInputSchema, IWaveVerifyTool;
|
|
221518
|
+
var init_verify$1 = __esmMin((() => {
|
|
221519
|
+
init_zod$1();
|
|
221520
|
+
init_instantiation();
|
|
221521
|
+
WaveVerifyToolInputSchema = object$1({
|
|
221522
|
+
task: string().min(3),
|
|
221523
|
+
root: string().optional(),
|
|
221524
|
+
ac: string().min(3).optional(),
|
|
221525
|
+
dryRun: boolean$1().optional(),
|
|
221526
|
+
allowDeclared: boolean$1().optional()
|
|
221527
|
+
}).strict();
|
|
221528
|
+
IWaveVerifyTool = createDecorator("waveVerifyTool");
|
|
220850
221529
|
}));
|
|
220851
221530
|
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verifyRunner.ts
|
|
221531
|
+
function failure$1(error) {
|
|
221532
|
+
return {
|
|
221533
|
+
output: error instanceof Error ? error.message : String(error),
|
|
221534
|
+
isError: true
|
|
221535
|
+
};
|
|
221536
|
+
}
|
|
221537
|
+
function runDry(root, config, input) {
|
|
221538
|
+
let selected;
|
|
221539
|
+
try {
|
|
221540
|
+
selected = selectTaskCriteria(nodeWaveFs, root, config, input.task, input.ac);
|
|
221541
|
+
} catch (error) {
|
|
221542
|
+
return failure$1(error);
|
|
221543
|
+
}
|
|
221544
|
+
const lines = [`TASK ${selected.taskId} · dryRun: no se ejecuta ningun comando`, ""];
|
|
221545
|
+
for (const ac of selected.criteria) {
|
|
221546
|
+
const falsifier = asRecord$2(ac["falsifier"]);
|
|
221547
|
+
lines.push(`dry ${asText$1(ac["id"])}`);
|
|
221548
|
+
lines.push(` verify: ${asText$1(ac["verify"])}`);
|
|
221549
|
+
lines.push(` mutacion: ${asText$1(falsifier["mutation"])}`);
|
|
221550
|
+
}
|
|
221551
|
+
lines.push("", `criterios ${selected.criteria.length} · comandos 0`);
|
|
221552
|
+
return { output: lines.join("\n") };
|
|
221553
|
+
}
|
|
220852
221554
|
function runWaveVerifyForRoot(input) {
|
|
220853
221555
|
const root = resolve(input.root);
|
|
220854
221556
|
const config = readWaveConfig(nodeWaveFs, root);
|
|
@@ -220856,7 +221558,16 @@ function runWaveVerifyForRoot(input) {
|
|
|
220856
221558
|
output: `no hay workflow.config.json en ${root}`,
|
|
220857
221559
|
isError: true
|
|
220858
221560
|
};
|
|
220859
|
-
|
|
221561
|
+
if (input.dryRun === true) return runDry(root, config, input);
|
|
221562
|
+
let result;
|
|
221563
|
+
try {
|
|
221564
|
+
result = verifyTask(nodeWaveFs, root, config, input.task, {
|
|
221565
|
+
ac: input.ac,
|
|
221566
|
+
allowDeclared: input.allowDeclared
|
|
221567
|
+
});
|
|
221568
|
+
} catch (error) {
|
|
221569
|
+
return failure$1(error);
|
|
221570
|
+
}
|
|
220860
221571
|
const lines = [`TASK ${result.taskId}`, ""];
|
|
220861
221572
|
for (const ac of result.acs) {
|
|
220862
221573
|
lines.push(`${ac.ok ? "ok " : "FAIL"} ${ac.acId} verify ${ac.verify.ok ? "verde" : "rojo"} mutante ${ac.mutant.state}`);
|
|
@@ -220872,13 +221583,14 @@ function runWaveVerifyForRoot(input) {
|
|
|
220872
221583
|
}
|
|
220873
221584
|
var init_verifyRunner = __esmMin((() => {
|
|
220874
221585
|
init_config$6();
|
|
221586
|
+
init_fsJson();
|
|
220875
221587
|
init_nodeFs();
|
|
220876
221588
|
init_runner();
|
|
220877
221589
|
}));
|
|
220878
221590
|
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verify.md?raw
|
|
220879
221591
|
var verify_default;
|
|
220880
221592
|
var init_verify = __esmMin((() => {
|
|
220881
|
-
verify_default = "Close a wave task with evidence: run each acceptance criterion's `verify` command and its falsifier.\n\nFor every criterion the tool runs `verify`, then `apply` of `falsifier.script`, then `verify` again (which must now fail), then `restore`, then `verify` once more (which must pass again). A criterion whose falsifier is only declared, whose mutant survives, or whose tree does not return to green is a failure — never a pass with a note.\n\nThe task id (`E01-T01`) is looked up in `backlog/tasks/`. Commands run without a shell and only with the binaries allowed by `vocabulary.verifyCommands`.\n";
|
|
221593
|
+
verify_default = "Close a wave task with evidence: run each acceptance criterion's `verify` command and its falsifier.\n\nFor every criterion the tool runs `verify`, then `apply` of `falsifier.script`, then `verify` again (which must now fail), then `restore`, then `verify` once more (which must pass again). A criterion whose falsifier is only declared, whose mutant survives, or whose tree does not return to green is a failure — never a pass with a note.\n\nThe task id (`E01-T01`) is looked up in `backlog/tasks/`. Commands run without a shell and only with the binaries allowed by `vocabulary.verifyCommands`.\n\nArguments:\n- `task`: task id to verify.\n- `root`: workspace root. Defaults to the current working directory.\n- `ac`: verify only this acceptance criterion instead of every criterion of the task. An id the task does not declare is rejected.\n- `dryRun`: list the criteria and the command each one would run without executing anything, so a coordinator can review before spending the run.\n";
|
|
220882
221594
|
}));
|
|
220883
221595
|
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verifyTool.ts
|
|
220884
221596
|
var WaveVerifyTool;
|
|
@@ -220904,7 +221616,10 @@ var init_verifyTool = __esmMin((() => {
|
|
|
220904
221616
|
approvalRule: this.name,
|
|
220905
221617
|
execute: () => Promise.resolve(runWaveVerifyForRoot({
|
|
220906
221618
|
root: args.root ?? this.sessionContext.cwd,
|
|
220907
|
-
task: args.task
|
|
221619
|
+
task: args.task,
|
|
221620
|
+
ac: args.ac,
|
|
221621
|
+
dryRun: args.dryRun,
|
|
221622
|
+
allowDeclared: args.allowDeclared
|
|
220908
221623
|
}))
|
|
220909
221624
|
};
|
|
220910
221625
|
}
|
|
@@ -220912,28 +221627,35 @@ var init_verifyTool = __esmMin((() => {
|
|
|
220912
221627
|
WaveVerifyTool = __decorate([__decorateParam(0, ISessionContext)], WaveVerifyTool);
|
|
220913
221628
|
}));
|
|
220914
221629
|
// ../../packages/agent-core-v2/src/features/wave/waveFeature.ts
|
|
221630
|
+
function profileHolds(accessor, profile) {
|
|
221631
|
+
return accessor.get(IAgentProfileService).data().profileName === profile;
|
|
221632
|
+
}
|
|
220915
221633
|
function isWaveFeatureAssembled(flags) {
|
|
220916
221634
|
return assembledOverrideForTests ?? assembledFlagServices.has(flags);
|
|
220917
221635
|
}
|
|
220918
221636
|
var WAVE_TOOL_CONTRIBUTIONS, WaveFeature, assembledFlagServices, assembledOverrideForTests;
|
|
220919
221637
|
var init_waveFeature = __esmMin((() => {
|
|
221638
|
+
init_instantiation();
|
|
221639
|
+
init_profile$1();
|
|
220920
221640
|
init_flag$7();
|
|
220921
221641
|
init_feature();
|
|
220922
221642
|
init_featureRegistry();
|
|
220923
|
-
|
|
221643
|
+
init_waveService();
|
|
221644
|
+
init_waveMode();
|
|
220924
221645
|
init_seatProfile();
|
|
221646
|
+
init_contract$4();
|
|
221647
|
+
init_contractTool();
|
|
220925
221648
|
init_decide$1();
|
|
220926
221649
|
init_decideTool();
|
|
220927
221650
|
init_gate$1();
|
|
221651
|
+
init_gateTool();
|
|
220928
221652
|
init_open$1();
|
|
220929
221653
|
init_openTool();
|
|
220930
|
-
init_round$1();
|
|
220931
|
-
init_roundTool();
|
|
220932
221654
|
init_submit$1();
|
|
220933
221655
|
init_submitTool();
|
|
220934
|
-
init_gateTool();
|
|
220935
221656
|
init_verify$1();
|
|
220936
221657
|
init_verifyTool();
|
|
221658
|
+
init_wave$3();
|
|
220937
221659
|
init_decorateParam();
|
|
220938
221660
|
init_decorate();
|
|
220939
221661
|
WAVE_TOOL_CONTRIBUTIONS = [
|
|
@@ -220957,15 +221679,15 @@ var init_waveFeature = __esmMin((() => {
|
|
|
220957
221679
|
ctor: WaveOpenTool,
|
|
220958
221680
|
name: "WaveOpen"
|
|
220959
221681
|
},
|
|
221682
|
+
{
|
|
221683
|
+
id: IWaveContractTool,
|
|
221684
|
+
ctor: WaveContractTool,
|
|
221685
|
+
name: "WaveContract"
|
|
221686
|
+
},
|
|
220960
221687
|
{
|
|
220961
221688
|
id: IWaveSubmitTool,
|
|
220962
221689
|
ctor: WaveSubmitTool,
|
|
220963
221690
|
name: "WaveSubmit"
|
|
220964
|
-
},
|
|
220965
|
-
{
|
|
220966
|
-
id: IWaveRoundTool,
|
|
220967
|
-
ctor: WaveRoundTool,
|
|
220968
|
-
name: "WaveRound"
|
|
220969
221691
|
}
|
|
220970
221692
|
];
|
|
220971
221693
|
WaveFeature = class WaveFeature extends Feature {
|
|
@@ -220977,10 +221699,15 @@ var init_waveFeature = __esmMin((() => {
|
|
|
220977
221699
|
this.onDispose(() => {
|
|
220978
221700
|
assembledFlagServices.delete(flags);
|
|
220979
221701
|
});
|
|
220980
|
-
|
|
220981
|
-
|
|
220982
|
-
|
|
220983
|
-
|
|
221702
|
+
this.contributeAgentService(IAgentWaveService, AgentWaveService, { activation: 0 });
|
|
221703
|
+
for (const tool of WAVE_TOOL_CONTRIBUTIONS) {
|
|
221704
|
+
const profile = tool.name === "WaveSubmit" ? WAVE_SEAT_PROFILE : WAVE_DIRECTOR_PROFILE;
|
|
221705
|
+
this.contributeTool(tool.id, tool.ctor, {
|
|
221706
|
+
name: tool.name,
|
|
221707
|
+
domain: WAVE_TOOL_DOMAIN,
|
|
221708
|
+
when: (accessor) => profileHolds(accessor, profile)
|
|
221709
|
+
});
|
|
221710
|
+
}
|
|
220984
221711
|
this.contributeProfiles([WAVE_SEAT_PROFILE_DEF]);
|
|
220985
221712
|
}
|
|
220986
221713
|
};
|
|
@@ -220995,7 +221722,7 @@ var init_flag$2 = __esmMin((() => {
|
|
|
220995
221722
|
init_wave$3();
|
|
220996
221723
|
init_waveFeature();
|
|
220997
221724
|
waveFlag = {
|
|
220998
|
-
id: WAVE_FLAG_ID
|
|
221725
|
+
id: WAVE_FLAG_ID,
|
|
220999
221726
|
title: "Wave workflow",
|
|
221000
221727
|
description: "Enable the wave workflow: adversarial design rounds with isolated seats, the package gate, and task verification tools.",
|
|
221001
221728
|
env: WAVE_FLAG_ENV,
|
|
@@ -221005,6 +221732,27 @@ var init_flag$2 = __esmMin((() => {
|
|
|
221005
221732
|
};
|
|
221006
221733
|
registerFlagDefinition(waveFlag);
|
|
221007
221734
|
}));
|
|
221735
|
+
var init_round = __esmMin((() => {
|
|
221736
|
+
init_zod$1();
|
|
221737
|
+
init_instantiation();
|
|
221738
|
+
object$1({
|
|
221739
|
+
wave: string().min(2),
|
|
221740
|
+
round: _enum([
|
|
221741
|
+
"propose",
|
|
221742
|
+
"defend",
|
|
221743
|
+
"attack",
|
|
221744
|
+
"judge",
|
|
221745
|
+
"refine",
|
|
221746
|
+
"audit"
|
|
221747
|
+
]),
|
|
221748
|
+
root: string().optional()
|
|
221749
|
+
}).strict();
|
|
221750
|
+
createDecorator("waveRoundTool");
|
|
221751
|
+
}));
|
|
221752
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/round/roundRunner.ts
|
|
221753
|
+
var init_roundRunner = __esmMin((() => {
|
|
221754
|
+
init_prompts$2();
|
|
221755
|
+
}));
|
|
221008
221756
|
// ../../packages/agent-core-v2/src/agent/usage/cacheProbe.ts
|
|
221009
221757
|
var IAgentCacheProbeService;
|
|
221010
221758
|
var init_cacheProbe = __esmMin((() => {
|
|
@@ -223569,6 +224317,7 @@ var AGENT_TOOLS, CODER_TOOLS, EXPLORE_TOOLS, CODER_ROLE;
|
|
|
223569
224317
|
var init_profiles = __esmMin((() => {
|
|
223570
224318
|
init_gitContext();
|
|
223571
224319
|
init_contribution();
|
|
224320
|
+
init_wave$3();
|
|
223572
224321
|
init_profile_shared();
|
|
223573
224322
|
init_explore_overlay();
|
|
223574
224323
|
AGENT_TOOLS = [
|
|
@@ -223603,6 +224352,8 @@ var init_profiles = __esmMin((() => {
|
|
|
223603
224352
|
"TowerStatus",
|
|
223604
224353
|
"TowerTeardown",
|
|
223605
224354
|
"WaveOpen",
|
|
224355
|
+
"WaveRound",
|
|
224356
|
+
"WaveContract",
|
|
223606
224357
|
"WaveSubmit",
|
|
223607
224358
|
"WaveGate",
|
|
223608
224359
|
"WaveDecide",
|
|
@@ -223649,7 +224400,8 @@ var init_profiles = __esmMin((() => {
|
|
|
223649
224400
|
subagents: [
|
|
223650
224401
|
"coder",
|
|
223651
224402
|
"explore",
|
|
223652
|
-
"plan"
|
|
224403
|
+
"plan",
|
|
224404
|
+
WAVE_SEAT_PROFILE
|
|
223653
224405
|
],
|
|
223654
224406
|
renderSystemPrompt: (context) => renderSystemPromptResult("", context, { skillActive: skillActiveFor(AGENT_TOOLS) })
|
|
223655
224407
|
});
|
|
@@ -281821,6 +282573,8 @@ var init_src$10 = __esmMin((() => {
|
|
|
281821
282573
|
init_flag$2();
|
|
281822
282574
|
init_wave$3();
|
|
281823
282575
|
init_waveFeature();
|
|
282576
|
+
init_waveMode();
|
|
282577
|
+
init_waveOps();
|
|
281824
282578
|
init_gate$1();
|
|
281825
282579
|
init_gateRunner();
|
|
281826
282580
|
init_decide$1();
|
|
@@ -281832,9 +282586,12 @@ var init_src$10 = __esmMin((() => {
|
|
|
281832
282586
|
init_submit$1();
|
|
281833
282587
|
init_submitRunner();
|
|
281834
282588
|
init_seatProfile();
|
|
281835
|
-
init_round
|
|
282589
|
+
init_round();
|
|
281836
282590
|
init_roundRunner();
|
|
281837
282591
|
init_prompts$2();
|
|
282592
|
+
init_seats();
|
|
282593
|
+
init_contract$4();
|
|
282594
|
+
init_contractRunner();
|
|
281838
282595
|
init_flag$2();
|
|
281839
282596
|
init_waveFeature();
|
|
281840
282597
|
init_usage();
|
|
@@ -288170,6 +288927,7 @@ var init_sdk_rpc_client_v2 = __esmMin((() => {
|
|
|
288170
288927
|
init_connection_manager();
|
|
288171
288928
|
init_towerRateLimit();
|
|
288172
288929
|
init_statusReader();
|
|
288930
|
+
init_waveMode();
|
|
288173
288931
|
init_configLoader();
|
|
288174
288932
|
init_fs$1();
|
|
288175
288933
|
init_appendLogStore$1();
|
|
@@ -289455,6 +290213,7 @@ var init_sdk_rpc_client_v2 = __esmMin((() => {
|
|
|
289455
290213
|
permission: agent.accessor.get(IAgentPermissionModeService).mode,
|
|
289456
290214
|
planMode: plan !== null,
|
|
289457
290215
|
swarmMode: agent.accessor.get(IAgentSwarmService).isActive,
|
|
290216
|
+
waveMode: agent.accessor.get(IAgentWaveService).isActive,
|
|
289458
290217
|
towerMode: agent.accessor.get(IAgentTowerService).isActive,
|
|
289459
290218
|
contextTokens,
|
|
289460
290219
|
maxContextTokens,
|
|
@@ -289742,6 +290501,11 @@ var init_sdk_rpc_client_v2 = __esmMin((() => {
|
|
|
289742
290501
|
});
|
|
289743
290502
|
return this.prompt(input);
|
|
289744
290503
|
}
|
|
290504
|
+
async setWaveMode(input) {
|
|
290505
|
+
const wave = (await this.agentScope(input.sessionId)).accessor.get(IAgentWaveService);
|
|
290506
|
+
if (input.enabled) await wave.enter();
|
|
290507
|
+
else await wave.exit();
|
|
290508
|
+
}
|
|
289745
290509
|
/** Through the agent scope (`IAgentTowerService.enter` / `.exit`) — no klient facade exists. */
|
|
289746
290510
|
async setTowerMode(input) {
|
|
289747
290511
|
const agent = await this.agentScope(input.sessionId);
|
|
@@ -394734,10 +395498,6 @@ function swarmArgumentCompletions(argumentPrefix) {
|
|
|
394734
395498
|
function towerArgumentCompletions(argumentPrefix) {
|
|
394735
395499
|
return completeLeadingArg(TOWER_ARG_COMPLETIONS, argumentPrefix);
|
|
394736
395500
|
}
|
|
394737
|
-
/** Argument autocompletion for the `/wave` command (subcommands). */
|
|
394738
|
-
function waveArgumentCompletions(argumentPrefix) {
|
|
394739
|
-
return completeLeadingArg(WAVE_ARG_COMPLETIONS, argumentPrefix);
|
|
394740
|
-
}
|
|
394741
395501
|
/** Argument autocompletion for the `/add-dir` command. */
|
|
394742
395502
|
function addDirArgumentCompletions(argumentPrefix) {
|
|
394743
395503
|
if (isPathLikeAddDirArgument(argumentPrefix)) return completeAddDirPath(argumentPrefix);
|
|
@@ -394817,7 +395577,7 @@ function resolveSlashCommandAvailability(command, args) {
|
|
|
394817
395577
|
function sortSlashCommands(commands) {
|
|
394818
395578
|
return [...commands].toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.name.localeCompare(b.name));
|
|
394819
395579
|
}
|
|
394820
|
-
var GOAL_ARG_COMPLETIONS, GOAL_NEXT_ARG_COMPLETIONS, SWARM_ARG_COMPLETIONS, TOWER_ARG_COMPLETIONS,
|
|
395580
|
+
var GOAL_ARG_COMPLETIONS, GOAL_NEXT_ARG_COMPLETIONS, SWARM_ARG_COMPLETIONS, TOWER_ARG_COMPLETIONS, ADD_DIR_ARG_COMPLETIONS, BUILTIN_SLASH_COMMANDS;
|
|
394821
395581
|
var init_registry$2 = __esmMin((() => {
|
|
394822
395582
|
init_dist$5();
|
|
394823
395583
|
init_complete_args();
|
|
@@ -394876,20 +395636,6 @@ var init_registry$2 = __esmMin((() => {
|
|
|
394876
395636
|
description: "Turn tower mode off"
|
|
394877
395637
|
}
|
|
394878
395638
|
];
|
|
394879
|
-
WAVE_ARG_COMPLETIONS = [
|
|
394880
|
-
{
|
|
394881
|
-
value: "on",
|
|
394882
|
-
description: "Enable the wave experiment"
|
|
394883
|
-
},
|
|
394884
|
-
{
|
|
394885
|
-
value: "off",
|
|
394886
|
-
description: "Disable the wave experiment"
|
|
394887
|
-
},
|
|
394888
|
-
{
|
|
394889
|
-
value: "status",
|
|
394890
|
-
description: "Report whether the wave experiment is on"
|
|
394891
|
-
}
|
|
394892
|
-
];
|
|
394893
395639
|
ADD_DIR_ARG_COMPLETIONS = [{
|
|
394894
395640
|
value: "list",
|
|
394895
395641
|
description: "Show configured additional workspace directories"
|
|
@@ -394952,12 +395698,9 @@ var init_registry$2 = __esmMin((() => {
|
|
|
394952
395698
|
{
|
|
394953
395699
|
name: "wave",
|
|
394954
395700
|
aliases: [],
|
|
394955
|
-
description: "
|
|
395701
|
+
description: "Turn the wave mode on or off, or open a design wave with an objective",
|
|
394956
395702
|
priority: 90,
|
|
394957
|
-
argumentHint: "[on|off
|
|
394958
|
-
completeArgs: waveArgumentCompletions,
|
|
394959
|
-
availability: "idle-only",
|
|
394960
|
-
experimentalFlag: "wave"
|
|
395703
|
+
argumentHint: "[on|off] | <objetivo de la oleada>"
|
|
394961
395704
|
},
|
|
394962
395705
|
{
|
|
394963
395706
|
name: "model",
|
|
@@ -471840,6 +472583,7 @@ var init_footer = __esmMin((() => {
|
|
|
471840
472583
|
if (state.permissionMode === "yolo") modes.push(chalk.hex(colors.warning).bold(PERMISSION_MODE_DISPLAY_NAMES.yolo));
|
|
471841
472584
|
if (state.planMode) modes.push(chalk.hex(colors.primary).bold("plan"));
|
|
471842
472585
|
if (state.swarmMode) modes.push(chalk.hex(colors.accent).bold("swarm"));
|
|
472586
|
+
if (state.waveMode) modes.push(chalk.hex(colors.accent).bold("wave"));
|
|
471843
472587
|
if (state.towerMode) modes.push(chalk.hex(colors.accent).bold("tower"));
|
|
471844
472588
|
if (modes.length > 0) slots["mode"] = [modes.join(" ")];
|
|
471845
472589
|
const goalBadge = formatGoalBadge(state.goal, colors, this.goalWallClockMs(state.goal));
|
|
@@ -477577,80 +478321,58 @@ var init_swarm = __esmMin((() => {
|
|
|
477577
478321
|
SWARM_USAGE_NOTICE = "High usage: Swarm is built for large parallel jobs and can use many times the tokens of a normal task. Start small, and run /swarm off when you're done.";
|
|
477578
478322
|
}));
|
|
477579
478323
|
// src/tui/commands/wave.ts
|
|
477580
|
-
function buildWavePrompt(
|
|
478324
|
+
function buildWavePrompt(objective) {
|
|
477581
478325
|
return [
|
|
477582
|
-
`
|
|
478326
|
+
`Abre una oleada del método workflow para: ${objective}`,
|
|
477583
478327
|
"",
|
|
477584
|
-
"Reglas
|
|
477585
|
-
"-
|
|
477586
|
-
"-
|
|
477587
|
-
"-
|
|
477588
|
-
"-
|
|
477589
|
-
"- Sin `adopt` de `WaveDecide`, lanza `refine` y después `audit`; con dos rondas sin quórum, adopta R1 con disidencia escrita.",
|
|
477590
|
-
"- La oleada no está cerrada hasta que `WaveGate` sale en verde. Si sale en rojo, dilo con los códigos de hallazgo."
|
|
478328
|
+
"Reglas:",
|
|
478329
|
+
"- Redacta primero el plan de la oleada (WaveOpen con nombre, alcance, evidencia y rondas) y crea el Goal con completionCriterion \"WaveGate verde sobre la oleada W<n> y WaveVerify 0 en todas sus tasks\".",
|
|
478330
|
+
"- No ejecutes la oleada en este turno: el plan se revisa antes de aprobarse.",
|
|
478331
|
+
"- Tras la aprobación, contrata con WaveContract y lanza un agente `wave-seat` por asiento. Tú no escribes artefactos: WaveSubmit es del asiento.",
|
|
478332
|
+
"- Cierras con WaveDecide, WaveVerify y WaveGate; la oleada no está cerrada hasta que WaveGate sale en verde."
|
|
477591
478333
|
].join("\n");
|
|
477592
478334
|
}
|
|
477593
478335
|
async function handleWaveCommand(host, args) {
|
|
477594
|
-
const
|
|
477595
|
-
|
|
477596
|
-
|
|
477597
|
-
await setWaveExperiment(host, sub === "on");
|
|
477598
|
-
return;
|
|
477599
|
-
}
|
|
477600
|
-
if (sub === "" || sub === "status") {
|
|
477601
|
-
await reportWaveStatus(host, sub === "");
|
|
478336
|
+
const session = host.session;
|
|
478337
|
+
if (session === void 0) {
|
|
478338
|
+
host.showError(NO_ACTIVE_SESSION_MESSAGE);
|
|
477602
478339
|
return;
|
|
477603
478340
|
}
|
|
477604
|
-
|
|
477605
|
-
|
|
478341
|
+
const input = args.trim();
|
|
478342
|
+
const command = input.toLowerCase();
|
|
478343
|
+
if (command === "on" || command === "off" || command === "") {
|
|
478344
|
+
await applyWaveMode(host, command === "" ? !host.state.appState.waveMode : command === "on");
|
|
477606
478345
|
return;
|
|
477607
478346
|
}
|
|
478347
|
+
if (!host.state.appState.waveMode && !await applyWaveMode(host, true)) return;
|
|
478348
|
+
if (!host.state.appState.planMode) await applyPlanMode(host, session, true);
|
|
477608
478349
|
host.sendNormalUserInput(buildWavePrompt(input));
|
|
477609
478350
|
}
|
|
477610
|
-
async function
|
|
477611
|
-
|
|
477612
|
-
|
|
477613
|
-
|
|
477614
|
-
} catch (error) {
|
|
477615
|
-
host.showError(`Failed to read the wave experiment state: ${formatErrorMessage$2(error)}`);
|
|
477616
|
-
return;
|
|
477617
|
-
}
|
|
477618
|
-
if (asUsage) {
|
|
477619
|
-
host.showNotice(`Wave experiment: ${enabled ? "ON" : "OFF"}`, `${WAVE_USAGE}\n\n${enabled ? "Las tools Wave están disponibles en esta sesión." : "Actívalo con `/wave on`; no hace falta editar config.toml ni reiniciar."}`);
|
|
477620
|
-
return;
|
|
477621
|
-
}
|
|
477622
|
-
host.showStatus(enabled ? "Wave experiment is on." : "Wave experiment is off. Run `/wave on` to enable it without a restart.");
|
|
477623
|
-
}
|
|
477624
|
-
async function setWaveExperiment(host, enabled) {
|
|
477625
|
-
try {
|
|
477626
|
-
await host.harness.setConfig({ experimental: { [WAVE_FLAG_ID]: enabled } });
|
|
477627
|
-
setExperimentalFeatures(await host.harness.getExperimentalFeatures());
|
|
477628
|
-
host.refreshSlashCommandAutocomplete();
|
|
477629
|
-
} catch (error) {
|
|
477630
|
-
host.showError(`Failed to ${enabled ? "enable" : "disable"} the wave experiment: ${formatErrorMessage$2(error)}`);
|
|
477631
|
-
return;
|
|
477632
|
-
}
|
|
477633
|
-
if (!enabled) {
|
|
477634
|
-
host.showStatus("Wave experiment off. `/wave` is hidden until you turn it back on.");
|
|
477635
|
-
return;
|
|
477636
|
-
}
|
|
477637
|
-
if (host.session === void 0) {
|
|
477638
|
-
host.showStatus("Wave experiment on. `/wave <objetivo>` is ready.", "success");
|
|
477639
|
-
return;
|
|
478351
|
+
async function applyWaveMode(host, enabled) {
|
|
478352
|
+
if (enabled === host.state.appState.waveMode) {
|
|
478353
|
+
host.showStatus(`Wave mode is already ${enabled ? "on" : "off"}.`);
|
|
478354
|
+
return true;
|
|
477640
478355
|
}
|
|
477641
478356
|
try {
|
|
477642
|
-
|
|
477643
|
-
await host.reloadCurrentSessionView(reloadedSession, "Wave experiment on. Session reloaded — `/wave <objetivo>` is ready.");
|
|
478357
|
+
await host.requireSession().setWaveMode(enabled);
|
|
477644
478358
|
} catch (error) {
|
|
477645
|
-
host.showError(`
|
|
478359
|
+
host.showError(`Failed to ${enabled ? "enable" : "disable"} wave mode: ${formatErrorMessage$2(error)}`);
|
|
478360
|
+
return false;
|
|
477646
478361
|
}
|
|
478362
|
+
host.setAppState({ waveMode: enabled });
|
|
478363
|
+
host.showNotice(`Wave mode: ${enabled ? "ON" : "OFF"}`);
|
|
478364
|
+
return true;
|
|
477647
478365
|
}
|
|
477648
|
-
var WAVE_USAGE, WAVE_FLAG_ID;
|
|
477649
478366
|
var init_wave = __esmMin((() => {
|
|
478367
|
+
init_nexgenk_tui();
|
|
477650
478368
|
init_event_payload();
|
|
477651
|
-
|
|
477652
|
-
|
|
477653
|
-
|
|
478369
|
+
init_config();
|
|
478370
|
+
[
|
|
478371
|
+
"Uso:",
|
|
478372
|
+
" /wave enciende o apaga el modo wave",
|
|
478373
|
+
" /wave off lo apaga",
|
|
478374
|
+
" /wave <objetivo> lo enciende y abre el plan de una oleada"
|
|
478375
|
+
].join("\n");
|
|
477654
478376
|
}));
|
|
477655
478377
|
// src/tui/commands/tower.ts
|
|
477656
478378
|
async function handleTowerCommand(host, args) {
|
|
@@ -484747,7 +485469,6 @@ var init_commands = __esmMin((() => {
|
|
|
484747
485469
|
init_config();
|
|
484748
485470
|
init_swarm();
|
|
484749
485471
|
init_tower();
|
|
484750
|
-
init_wave();
|
|
484751
485472
|
init_info();
|
|
484752
485473
|
init_plugins();
|
|
484753
485474
|
init_reload();
|
|
@@ -494367,6 +495088,7 @@ var SessionEventHandler = class {
|
|
|
494367
495088
|
}
|
|
494368
495089
|
if (event.planMode !== void 0) patch.planMode = event.planMode;
|
|
494369
495090
|
if (event.swarmMode !== void 0) patch.swarmMode = event.swarmMode;
|
|
495091
|
+
if (event.waveMode !== void 0) patch.waveMode = event.waveMode;
|
|
494370
495092
|
if (event.towerMode !== void 0) patch.towerMode = event.towerMode;
|
|
494371
495093
|
if (event.permission !== void 0) patch.permissionMode = event.permission;
|
|
494372
495094
|
if (event.model !== void 0) patch.model = event.model;
|
|
@@ -499535,6 +500257,7 @@ function createInitialAppState(input) {
|
|
|
499535
500257
|
planMode: input.cliOptions.plan,
|
|
499536
500258
|
inputMode: "prompt",
|
|
499537
500259
|
swarmMode: false,
|
|
500260
|
+
waveMode: false,
|
|
499538
500261
|
towerMode: false,
|
|
499539
500262
|
thinkingEffort: "off",
|
|
499540
500263
|
contextUsage: 0,
|
|
@@ -501304,6 +502027,7 @@ var NexgenTUI = class {
|
|
|
501304
502027
|
permissionMode: status.permission,
|
|
501305
502028
|
planMode: status.planMode,
|
|
501306
502029
|
swarmMode: status.swarmMode ?? false,
|
|
502030
|
+
waveMode: status.waveMode ?? false,
|
|
501307
502031
|
towerMode: status.towerMode ?? false,
|
|
501308
502032
|
contextTokens: status.contextTokens,
|
|
501309
502033
|
maxContextTokens: status.maxContextTokens,
|