nexgenk 1.4.1 → 1.5.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 +934 -488
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -111222,7 +111222,7 @@ function dump$1(input, options) {
|
|
|
111222
111222
|
if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
|
|
111223
111223
|
return "";
|
|
111224
111224
|
}
|
|
111225
|
-
var common, exception, snippet, TYPE_CONSTRUCTOR_OPTIONS, YAML_NODE_KINDS, type$2, schema, str$3, seq, map, failsafe, _null, bool
|
|
111225
|
+
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
111226
|
var init_js_yaml = __esmMin((() => {
|
|
111227
111227
|
common = {
|
|
111228
111228
|
isNothing,
|
|
@@ -111330,7 +111330,7 @@ var init_js_yaml = __esmMin((() => {
|
|
|
111330
111330
|
},
|
|
111331
111331
|
defaultStyle: "lowercase"
|
|
111332
111332
|
});
|
|
111333
|
-
bool
|
|
111333
|
+
bool = new type$2("tag:yaml.org,2002:bool", {
|
|
111334
111334
|
kind: "scalar",
|
|
111335
111335
|
resolve: resolveYamlBoolean,
|
|
111336
111336
|
construct: constructYamlBoolean,
|
|
@@ -111387,7 +111387,7 @@ var init_js_yaml = __esmMin((() => {
|
|
|
111387
111387
|
});
|
|
111388
111388
|
json = failsafe.extend({ implicit: [
|
|
111389
111389
|
_null,
|
|
111390
|
-
bool
|
|
111390
|
+
bool,
|
|
111391
111391
|
int,
|
|
111392
111392
|
float
|
|
111393
111393
|
] });
|
|
@@ -125575,9 +125575,9 @@ var init_update_config = __esmMin((() => {
|
|
|
125575
125575
|
};
|
|
125576
125576
|
}));
|
|
125577
125577
|
// ../../packages/agent-core-v2/src/features/wave/wave.ts
|
|
125578
|
-
var WAVE_FLAG_ID
|
|
125578
|
+
var WAVE_FLAG_ID, WAVE_FLAG_ENV, WAVE_SEAT_PROFILE, WAVE_TOOL_DOMAIN;
|
|
125579
125579
|
var init_wave$3 = __esmMin((() => {
|
|
125580
|
-
WAVE_FLAG_ID
|
|
125580
|
+
WAVE_FLAG_ID = "wave";
|
|
125581
125581
|
WAVE_FLAG_ENV = "NEXGEN_EXPERIMENTAL_WAVE";
|
|
125582
125582
|
WAVE_SEAT_PROFILE = "wave-seat";
|
|
125583
125583
|
WAVE_TOOL_DOMAIN = "wave";
|
|
@@ -125604,7 +125604,7 @@ var init_wave$1 = __esmMin((() => {
|
|
|
125604
125604
|
...parsed$1,
|
|
125605
125605
|
path: PSEUDO_PATH$1,
|
|
125606
125606
|
dir: PSEUDO_PATH$1,
|
|
125607
|
-
experimentalFlag: WAVE_FLAG_ID
|
|
125607
|
+
experimentalFlag: WAVE_FLAG_ID,
|
|
125608
125608
|
metadata: {
|
|
125609
125609
|
...parsed$1.metadata,
|
|
125610
125610
|
type: parsed$1.metadata.type ?? "inline"
|
|
@@ -219297,6 +219297,26 @@ var init_decide$1 = __esmMin((() => {
|
|
|
219297
219297
|
IWaveDecideTool = createDecorator("waveDecideTool");
|
|
219298
219298
|
}));
|
|
219299
219299
|
// ../../packages/agent-core-v2/src/features/wave/core/config.ts
|
|
219300
|
+
function seats(prefix, count) {
|
|
219301
|
+
return Array.from({ length: Math.max(0, count) }, (_, index) => `${prefix}${index + 1}`);
|
|
219302
|
+
}
|
|
219303
|
+
function waveRoundSeats(roles, round) {
|
|
219304
|
+
if (round === "propose") return seats("P", roles.proponents);
|
|
219305
|
+
if (round === "defend") return seats("D", roles.defenders);
|
|
219306
|
+
if (round === "attack") return seats("A", roles.adversaries);
|
|
219307
|
+
if (round === "judge") return seats("J", roles.judges);
|
|
219308
|
+
const refiners = seats("R", roles.refiners);
|
|
219309
|
+
return round === "refine" ? refiners.slice(0, 1) : refiners.slice(1);
|
|
219310
|
+
}
|
|
219311
|
+
function waveConfigState(config) {
|
|
219312
|
+
const state = config;
|
|
219313
|
+
return {
|
|
219314
|
+
...config,
|
|
219315
|
+
version: state.version ?? 1,
|
|
219316
|
+
wavesOpen: state.wavesOpen ?? [],
|
|
219317
|
+
raw: state.raw ?? {}
|
|
219318
|
+
};
|
|
219319
|
+
}
|
|
219300
219320
|
function record$2(value) {
|
|
219301
219321
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
219302
219322
|
}
|
|
@@ -219306,9 +219326,6 @@ function num(value, fallback) {
|
|
|
219306
219326
|
function text(value, fallback) {
|
|
219307
219327
|
return typeof value === "string" ? value : fallback;
|
|
219308
219328
|
}
|
|
219309
|
-
function bool(value, fallback) {
|
|
219310
|
-
return typeof value === "boolean" ? value : fallback;
|
|
219311
|
-
}
|
|
219312
219329
|
function strArray$1(value, fallback) {
|
|
219313
219330
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : fallback;
|
|
219314
219331
|
}
|
|
@@ -219320,6 +219337,9 @@ function makeWaveConfig(raw, loadedFrom) {
|
|
|
219320
219337
|
const roles = record$2(base["roles"]);
|
|
219321
219338
|
const quorum = record$2(base["quorum"]);
|
|
219322
219339
|
return {
|
|
219340
|
+
version: num(base["version"], 1),
|
|
219341
|
+
wavesOpen: strArray$1(base["wavesOpen"], []),
|
|
219342
|
+
raw: base,
|
|
219323
219343
|
layout: {
|
|
219324
219344
|
waves: text(layout["waves"], DEFAULT_LAYOUT.waves),
|
|
219325
219345
|
backlog: text(layout["backlog"], DEFAULT_LAYOUT.backlog),
|
|
@@ -219338,8 +219358,7 @@ function makeWaveConfig(raw, loadedFrom) {
|
|
|
219338
219358
|
minGoalChars: num(thresholds["minGoalChars"], DEFAULT_THRESHOLDS.minGoalChars),
|
|
219339
219359
|
minScopeChars: num(thresholds["minScopeChars"], DEFAULT_THRESHOLDS.minScopeChars),
|
|
219340
219360
|
minFieldChars: num(thresholds["minFieldChars"], DEFAULT_THRESHOLDS.minFieldChars),
|
|
219341
|
-
minMetricChars: num(thresholds["minMetricChars"], DEFAULT_THRESHOLDS.minMetricChars)
|
|
219342
|
-
allowVerifyTargetMissing: bool(thresholds["allowVerifyTargetMissing"], DEFAULT_THRESHOLDS.allowVerifyTargetMissing)
|
|
219361
|
+
minMetricChars: num(thresholds["minMetricChars"], DEFAULT_THRESHOLDS.minMetricChars)
|
|
219343
219362
|
},
|
|
219344
219363
|
vocabulary: {
|
|
219345
219364
|
areas: strArray$1(vocabulary["areas"], DEFAULT_VOCABULARY.areas),
|
|
@@ -219363,8 +219382,7 @@ function makeWaveConfig(raw, loadedFrom) {
|
|
|
219363
219382
|
minAxes: num(quorum["minAxes"], DEFAULT_QUORUM.minAxes),
|
|
219364
219383
|
axes: strArray$1(quorum["axes"], DEFAULT_QUORUM.axes)
|
|
219365
219384
|
},
|
|
219366
|
-
loadedFrom
|
|
219367
|
-
missingKeys: CONFIG_REQUIRED_KEYS.filter((key) => base[key] === void 0)
|
|
219385
|
+
loadedFrom
|
|
219368
219386
|
};
|
|
219369
219387
|
}
|
|
219370
219388
|
function readWaveConfig(fs, root) {
|
|
@@ -219383,8 +219401,24 @@ function containedPath(root, candidate) {
|
|
|
219383
219401
|
if (resolved !== resolvedRoot && !resolved.startsWith(`${resolvedRoot}${sep}`)) throw new Error(`ruta fuera del workspace: ${candidate}`);
|
|
219384
219402
|
return resolved;
|
|
219385
219403
|
}
|
|
219386
|
-
var DEFAULT_LAYOUT, DEFAULT_THRESHOLDS, DEFAULT_VOCABULARY, DEFAULT_ROLES, DEFAULT_QUORUM
|
|
219404
|
+
var WAVE_ROUNDS, WAVE_ROUND_DIRS, DEFAULT_LAYOUT, DEFAULT_THRESHOLDS, DEFAULT_VOCABULARY, DEFAULT_ROLES, DEFAULT_QUORUM;
|
|
219387
219405
|
var init_config$6 = __esmMin((() => {
|
|
219406
|
+
WAVE_ROUNDS = [
|
|
219407
|
+
"propose",
|
|
219408
|
+
"defend",
|
|
219409
|
+
"attack",
|
|
219410
|
+
"judge",
|
|
219411
|
+
"refine",
|
|
219412
|
+
"audit"
|
|
219413
|
+
];
|
|
219414
|
+
WAVE_ROUND_DIRS = {
|
|
219415
|
+
propose: "01-proposals",
|
|
219416
|
+
defend: "02-defenses",
|
|
219417
|
+
attack: "03-attacks",
|
|
219418
|
+
judge: "04-verdicts",
|
|
219419
|
+
refine: "05-refined",
|
|
219420
|
+
audit: "05-refined"
|
|
219421
|
+
};
|
|
219388
219422
|
DEFAULT_LAYOUT = {
|
|
219389
219423
|
waves: "design/waves",
|
|
219390
219424
|
backlog: "backlog",
|
|
@@ -219402,8 +219436,7 @@ var init_config$6 = __esmMin((() => {
|
|
|
219402
219436
|
minGoalChars: 40,
|
|
219403
219437
|
minScopeChars: 40,
|
|
219404
219438
|
minFieldChars: 10,
|
|
219405
|
-
minMetricChars: 4
|
|
219406
|
-
allowVerifyTargetMissing: false
|
|
219439
|
+
minMetricChars: 4
|
|
219407
219440
|
};
|
|
219408
219441
|
DEFAULT_VOCABULARY = {
|
|
219409
219442
|
areas: [
|
|
@@ -219482,13 +219515,6 @@ var init_config$6 = __esmMin((() => {
|
|
|
219482
219515
|
"encaje"
|
|
219483
219516
|
]
|
|
219484
219517
|
};
|
|
219485
|
-
CONFIG_REQUIRED_KEYS = [
|
|
219486
|
-
"version",
|
|
219487
|
-
"layout",
|
|
219488
|
-
"waves",
|
|
219489
|
-
"thresholds",
|
|
219490
|
-
"vocabulary"
|
|
219491
|
-
];
|
|
219492
219518
|
}));
|
|
219493
219519
|
// ../../packages/agent-core-v2/src/features/wave/core/nodeFs.ts
|
|
219494
219520
|
var nodeWaveFs;
|
|
@@ -219574,17 +219600,13 @@ function evaluateQuorum(input) {
|
|
|
219574
219600
|
if (winner === void 0) throw new Error("no hay propuestas que comparar");
|
|
219575
219601
|
if (second === void 0) return {
|
|
219576
219602
|
verdict: "refine",
|
|
219577
|
-
winner
|
|
219603
|
+
winner,
|
|
219578
219604
|
second: void 0,
|
|
219579
219605
|
medians,
|
|
219580
219606
|
medianMargin: 0,
|
|
219581
219607
|
judgesHoldingMargin: 0,
|
|
219582
|
-
perJudge:
|
|
219583
|
-
|
|
219584
|
-
margin: 0,
|
|
219585
|
-
holds: false
|
|
219586
|
-
})),
|
|
219587
|
-
reason: `solo hay una propuesta (${winner}): sin comparacion no hay quorum`
|
|
219608
|
+
perJudge: [],
|
|
219609
|
+
reason: `sin comparacion no hay quorum: solo hay una propuesta (${winner})`
|
|
219588
219610
|
};
|
|
219589
219611
|
const winnerMedian = medians[winner] ?? 0;
|
|
219590
219612
|
const secondMedian = medians[second] ?? 0;
|
|
@@ -219609,8 +219631,7 @@ function evaluateQuorum(input) {
|
|
|
219609
219631
|
});
|
|
219610
219632
|
const judgesHoldingMargin = perJudge.filter((entry) => entry.holds).length;
|
|
219611
219633
|
const marginOk = medianMargin >= minPoints;
|
|
219612
|
-
const
|
|
219613
|
-
const majorityOk = judgesHoldingMargin >= requiredJudges;
|
|
219634
|
+
const majorityOk = judgesHoldingMargin >= minAxes;
|
|
219614
219635
|
if (marginOk && majorityOk) return {
|
|
219615
219636
|
verdict: "adopt",
|
|
219616
219637
|
winner,
|
|
@@ -219619,9 +219640,9 @@ function evaluateQuorum(input) {
|
|
|
219619
219640
|
medianMargin,
|
|
219620
219641
|
judgesHoldingMargin,
|
|
219621
219642
|
perJudge,
|
|
219622
|
-
reason: `mediana ${winner} ${winnerMedian} vs ${second} ${secondMedian}: margen ${medianMargin} en ${judgesHoldingMargin}/${perJudge.length} jueces
|
|
219643
|
+
reason: `mediana ${winner} ${winnerMedian} vs ${second} ${secondMedian}: margen ${medianMargin} en ${judgesHoldingMargin}/${perJudge.length} jueces`
|
|
219623
219644
|
};
|
|
219624
|
-
const reason = [marginOk ? void 0 : `margen ${medianMargin} < ${minPoints}`, majorityOk ? void 0 : `solo ${judgesHoldingMargin}/${perJudge.length} jueces superan el margen (minimo ${
|
|
219645
|
+
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
219646
|
return {
|
|
219626
219647
|
verdict: round >= 2 ? "deadlock" : "refine",
|
|
219627
219648
|
winner,
|
|
@@ -219656,6 +219677,7 @@ function runWaveDecideForRoot(input) {
|
|
|
219656
219677
|
isError: true
|
|
219657
219678
|
};
|
|
219658
219679
|
}
|
|
219680
|
+
const holding = result.perJudge.length === 0 ? "sin comparacion" : `${result.judgesHoldingMargin}/${result.perJudge.length}`;
|
|
219659
219681
|
const lines = [
|
|
219660
219682
|
`QUORUM — ${result.verdict}`,
|
|
219661
219683
|
"",
|
|
@@ -219663,8 +219685,9 @@ function runWaveDecideForRoot(input) {
|
|
|
219663
219685
|
"",
|
|
219664
219686
|
` ganador: ${result.winner ?? "(empate)"}`,
|
|
219665
219687
|
` margen: ${result.medianMargin} (minimo ${input.minPoints ?? config.quorum.minPoints})`,
|
|
219666
|
-
` jueces con margen: ${
|
|
219688
|
+
` jueces con margen: ${holding} (minimo ${input.minAxes ?? config.quorum.minAxes})`,
|
|
219667
219689
|
...result.perJudge.map((entry) => ` ${entry.judge}: ${entry.margin}${entry.holds ? " ok" : " NO"}`),
|
|
219690
|
+
...result.perJudge.filter((entry) => entry.margin < 0).map((entry) => ` disidencia: ${entry.judge} ${entry.margin}`),
|
|
219668
219691
|
"",
|
|
219669
219692
|
` motivo: ${result.reason}`
|
|
219670
219693
|
];
|
|
@@ -219682,7 +219705,7 @@ var init_decideRunner = __esmMin((() => {
|
|
|
219682
219705
|
// ../../packages/agent-core-v2/src/features/wave/tools/decide/decide.md?raw
|
|
219683
219706
|
var decide_default;
|
|
219684
219707
|
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
|
|
219708
|
+
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
219709
|
}));
|
|
219687
219710
|
// ../../packages/agent-core-v2/src/features/wave/tools/decide/decideTool.ts
|
|
219688
219711
|
var WaveDecideTool;
|
|
@@ -219778,6 +219801,18 @@ function walk$1(fs, dir, accept, acc = []) {
|
|
|
219778
219801
|
}
|
|
219779
219802
|
var init_fsJson = __esmMin((() => {}));
|
|
219780
219803
|
// ../../packages/agent-core-v2/src/features/wave/tools/open/openRunner.ts
|
|
219804
|
+
function briefTemplate(root) {
|
|
219805
|
+
const fs = nodeWaveFs;
|
|
219806
|
+
const local = join(root, BRIEF_TEMPLATE$1);
|
|
219807
|
+
if (fs.exists(local)) return { file: local };
|
|
219808
|
+
if (fs.isDirectory(join(root, "workflow"))) return { missing: BRIEF_TEMPLATE$1 };
|
|
219809
|
+
return fs.exists(BUNDLED_BRIEF_TEMPLATE) ? { file: BUNDLED_BRIEF_TEMPLATE } : { missing: BRIEF_TEMPLATE$1 };
|
|
219810
|
+
}
|
|
219811
|
+
function nextEpic(backlogDir) {
|
|
219812
|
+
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);
|
|
219813
|
+
const next = numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
219814
|
+
return `E${String(next).padStart(2, "0")}`;
|
|
219815
|
+
}
|
|
219781
219816
|
function slugify(name) {
|
|
219782
219817
|
return name.normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "");
|
|
219783
219818
|
}
|
|
@@ -219791,15 +219826,29 @@ function runWaveOpenForRoot(input) {
|
|
|
219791
219826
|
};
|
|
219792
219827
|
const layout = asRecord$2(asRecord$2(rawConfig)["layout"]);
|
|
219793
219828
|
const wavesRel = typeof layout["waves"] === "string" ? layout["waves"] : "design/waves";
|
|
219829
|
+
const backlogRel = typeof layout["backlog"] === "string" ? layout["backlog"] : "backlog";
|
|
219830
|
+
const minimum = makeWaveConfig(rawConfig).thresholds.minBriefSections;
|
|
219794
219831
|
let wavesDir;
|
|
219832
|
+
let backlogDir;
|
|
219795
219833
|
try {
|
|
219796
219834
|
wavesDir = containedPath(input.root, wavesRel);
|
|
219835
|
+
backlogDir = containedPath(input.root, backlogRel);
|
|
219797
219836
|
} catch (error) {
|
|
219798
219837
|
return {
|
|
219799
219838
|
output: error instanceof Error ? error.message : String(error),
|
|
219800
219839
|
isError: true
|
|
219801
219840
|
};
|
|
219802
219841
|
}
|
|
219842
|
+
const template = briefTemplate(input.root);
|
|
219843
|
+
if (template.file === void 0) return {
|
|
219844
|
+
output: `falta ${template.missing ?? BRIEF_TEMPLATE$1}: no se genera un brief sin la plantilla unica`,
|
|
219845
|
+
isError: true
|
|
219846
|
+
};
|
|
219847
|
+
const source = fs.read(template.file);
|
|
219848
|
+
if (source === void 0) return {
|
|
219849
|
+
output: `no se pudo leer ${template.file}`,
|
|
219850
|
+
isError: true
|
|
219851
|
+
};
|
|
219803
219852
|
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));
|
|
219804
219853
|
const next = input.id ?? `W${existing.length > 0 ? Math.max(...existing) + 1 : 0}`;
|
|
219805
219854
|
if (!/^W\d{1,2}$/.test(next)) return {
|
|
@@ -219816,8 +219865,9 @@ function runWaveOpenForRoot(input) {
|
|
|
219816
219865
|
isError: true
|
|
219817
219866
|
};
|
|
219818
219867
|
const dir = join(wavesDir, `${next}-${slug}`);
|
|
219868
|
+
const brief = source.replaceAll("{{WAVE}}", next).replaceAll("{{NAME}}", slug).replaceAll("{{NEXT_EPIC}}", nextEpic(backlogDir));
|
|
219819
219869
|
for (const sub of SUBDIRS) fs.mkdir(join(dir, sub));
|
|
219820
|
-
fs.write(join(dir, "00-brief.md"),
|
|
219870
|
+
fs.write(join(dir, "00-brief.md"), brief);
|
|
219821
219871
|
const declared = asArray$2(asRecord$2(rawConfig)["waves"]).map(String);
|
|
219822
219872
|
if (!declared.includes(next)) writeJson(fs, configFile, {
|
|
219823
219873
|
...asRecord$2(rawConfig),
|
|
@@ -219825,11 +219875,11 @@ function runWaveOpenForRoot(input) {
|
|
|
219825
219875
|
});
|
|
219826
219876
|
return { output: [
|
|
219827
219877
|
`oleada creada: ${next}-${slug}`,
|
|
219828
|
-
` brief: ${wavesRel}/${next}-${slug}/00-brief.md (rellena las
|
|
219878
|
+
` brief: ${wavesRel}/${next}-${slug}/00-brief.md (rellena las ${minimum} secciones antes de lanzar asientos)`,
|
|
219829
219879
|
` config: ${next} declarada en workflow.config.json (el gate la exige desde ahora)`
|
|
219830
219880
|
].join("\n") };
|
|
219831
219881
|
}
|
|
219832
|
-
var SUBDIRS,
|
|
219882
|
+
var SUBDIRS, BRIEF_TEMPLATE$1, BUNDLED_BRIEF_TEMPLATE;
|
|
219833
219883
|
var init_openRunner = __esmMin((() => {
|
|
219834
219884
|
init_config$6();
|
|
219835
219885
|
init_fsJson();
|
|
@@ -219841,24 +219891,8 @@ var init_openRunner = __esmMin((() => {
|
|
|
219841
219891
|
"04-verdicts",
|
|
219842
219892
|
"05-refined"
|
|
219843
219893
|
];
|
|
219844
|
-
|
|
219845
|
-
|
|
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");
|
|
219894
|
+
BRIEF_TEMPLATE$1 = "workflow/templates/brief.md";
|
|
219895
|
+
BUNDLED_BRIEF_TEMPLATE = resolve(import.meta.dirname, "../../../../../../../workflow/templates/brief.md");
|
|
219862
219896
|
}));
|
|
219863
219897
|
// ../../packages/agent-core-v2/src/features/wave/tools/open/open.md?raw
|
|
219864
219898
|
var open_default;
|
|
@@ -219916,6 +219950,85 @@ var init_round$1 = __esmMin((() => {
|
|
|
219916
219950
|
}).strict();
|
|
219917
219951
|
IWaveRoundTool = createDecorator("waveRoundTool");
|
|
219918
219952
|
}));
|
|
219953
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitRunner.ts
|
|
219954
|
+
function seatTicketHash(ticket) {
|
|
219955
|
+
return createHash("sha256").update(ticket).digest("hex");
|
|
219956
|
+
}
|
|
219957
|
+
function findWaveDir(root, wavesRel, wave) {
|
|
219958
|
+
const fs = nodeWaveFs;
|
|
219959
|
+
const wavesDir = containedPath(root, wavesRel);
|
|
219960
|
+
const name = fs.list(wavesDir).filter((entry) => fs.isDirectory(join(wavesDir, entry))).find((entry) => entry === wave || entry.startsWith(`${wave}-`));
|
|
219961
|
+
return name === void 0 ? void 0 : join(wavesDir, name);
|
|
219962
|
+
}
|
|
219963
|
+
function runWaveSubmitForRoot(input) {
|
|
219964
|
+
const fs = nodeWaveFs;
|
|
219965
|
+
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
219966
|
+
if (rawConfig === void 0) return {
|
|
219967
|
+
output: `no hay workflow.config.json en ${input.root}`,
|
|
219968
|
+
isError: true
|
|
219969
|
+
};
|
|
219970
|
+
const config = makeWaveConfig(rawConfig);
|
|
219971
|
+
const wavesRel = config.layout.waves;
|
|
219972
|
+
const seats = waveRoundSeats(config.roles, input.round);
|
|
219973
|
+
if (!seats.includes(input.role)) return {
|
|
219974
|
+
output: `seats.unknown_seat: el rol "${input.role}" no pertenece a la ronda ${input.round} (esperado ${seats.join(", ")})`,
|
|
219975
|
+
isError: true
|
|
219976
|
+
};
|
|
219977
|
+
let base;
|
|
219978
|
+
try {
|
|
219979
|
+
base = findWaveDir(input.root, wavesRel, input.wave);
|
|
219980
|
+
} catch (error) {
|
|
219981
|
+
return {
|
|
219982
|
+
output: error instanceof Error ? error.message : String(error),
|
|
219983
|
+
isError: true
|
|
219984
|
+
};
|
|
219985
|
+
}
|
|
219986
|
+
if (base === void 0) return {
|
|
219987
|
+
output: `no existe la oleada ${input.wave} en ${wavesRel}`,
|
|
219988
|
+
isError: true
|
|
219989
|
+
};
|
|
219990
|
+
const dirName = WAVE_ROUND_DIRS[input.round];
|
|
219991
|
+
const dir = join(base, dirName);
|
|
219992
|
+
if (!fs.isDirectory(dir)) return {
|
|
219993
|
+
output: `falta el directorio ${dirName} en la oleada ${input.wave}`,
|
|
219994
|
+
isError: true
|
|
219995
|
+
};
|
|
219996
|
+
const seatsDir = join(base, WAVE_SEATS_DIR);
|
|
219997
|
+
if (fs.isDirectory(seatsDir) && fs.list(seatsDir).length > 0) {
|
|
219998
|
+
const presented = (input.ticket ?? "").trim();
|
|
219999
|
+
if (presented === "") return {
|
|
220000
|
+
output: `seats.foreign_replace: el asiento ${input.role} no presento el ticket que emitio la ronda`,
|
|
220001
|
+
isError: true
|
|
220002
|
+
};
|
|
220003
|
+
const stored = (fs.read(join(seatsDir, input.role)) ?? "").trim();
|
|
220004
|
+
if (stored === "" || stored !== seatTicketHash(presented)) return {
|
|
220005
|
+
output: `seats.foreign_replace: el ticket presentado no es el del asiento ${input.role}`,
|
|
220006
|
+
isError: true
|
|
220007
|
+
};
|
|
220008
|
+
if (input.replace === true && (input.reason ?? "").trim() === "") return {
|
|
220009
|
+
output: `seats.replace_without_reason: reescribir el artefacto del asiento ${input.role} exige un motivo no vacio`,
|
|
220010
|
+
isError: true
|
|
220011
|
+
};
|
|
220012
|
+
}
|
|
220013
|
+
const file = join(dir, `${input.role}.md`);
|
|
220014
|
+
if (fs.exists(file) && input.replace !== true) return {
|
|
220015
|
+
output: `el asiento ${input.role} ya entrego su artefacto; un asiento escribe una vez (usa replace solo para relanzar un fallo)`,
|
|
220016
|
+
isError: true
|
|
220017
|
+
};
|
|
220018
|
+
if (input.artifact.trim() === "") return {
|
|
220019
|
+
output: "el artefacto esta vacio: un asiento que no escribe, fallo",
|
|
220020
|
+
isError: true
|
|
220021
|
+
};
|
|
220022
|
+
fs.write(file, input.artifact.endsWith("\n") ? input.artifact : `${input.artifact}\n`);
|
|
220023
|
+
return { output: `escrito ${wavesRel}/${base.split("/").pop()}/${dirName}/${input.role}.md` };
|
|
220024
|
+
}
|
|
220025
|
+
var WAVE_SEATS_DIR;
|
|
220026
|
+
var init_submitRunner = __esmMin((() => {
|
|
220027
|
+
init_config$6();
|
|
220028
|
+
init_fsJson();
|
|
220029
|
+
init_nodeFs();
|
|
220030
|
+
WAVE_SEATS_DIR = ".seats";
|
|
220031
|
+
}));
|
|
219919
220032
|
// ../../packages/agent-core-v2/src/features/wave/tools/round/prompts.ts
|
|
219920
220033
|
var SEAT_PRELUDE, ROLE_PROMPTS, JUDGE_BIASES;
|
|
219921
220034
|
var init_prompts$2 = __esmMin((() => {
|
|
@@ -219943,16 +220056,6 @@ var init_prompts$2 = __esmMin((() => {
|
|
|
219943
220056
|
];
|
|
219944
220057
|
}));
|
|
219945
220058
|
// ../../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
|
-
}
|
|
219956
220059
|
function runWaveRoundForRoot(input) {
|
|
219957
220060
|
const fs = nodeWaveFs;
|
|
219958
220061
|
const rawConfig = readJson$2(fs, join(input.root, "workflow.config.json"));
|
|
@@ -219961,9 +220064,8 @@ function runWaveRoundForRoot(input) {
|
|
|
219961
220064
|
seats: [],
|
|
219962
220065
|
isError: true
|
|
219963
220066
|
};
|
|
219964
|
-
const config =
|
|
219965
|
-
const
|
|
219966
|
-
const wavesRel = typeof layout["waves"] === "string" ? layout["waves"] : "design/waves";
|
|
220067
|
+
const config = makeWaveConfig(rawConfig);
|
|
220068
|
+
const wavesRel = config.layout.waves;
|
|
219967
220069
|
let wavesDir;
|
|
219968
220070
|
try {
|
|
219969
220071
|
wavesDir = containedPath(input.root, wavesRel);
|
|
@@ -219988,35 +220090,35 @@ function runWaveRoundForRoot(input) {
|
|
|
219988
220090
|
isError: true
|
|
219989
220091
|
};
|
|
219990
220092
|
const sections = brief.match(/^##\s+\S/gm)?.length ?? 0;
|
|
219991
|
-
|
|
219992
|
-
|
|
220093
|
+
const minimum = config.thresholds.minBriefSections;
|
|
220094
|
+
if (sections < minimum) return {
|
|
220095
|
+
output: `el brief tiene ${sections} secciones < ${minimum}: rellena las ${minimum} antes de lanzar la ronda`,
|
|
219993
220096
|
seats: [],
|
|
219994
220097
|
isError: true
|
|
219995
220098
|
};
|
|
219996
|
-
const
|
|
219997
|
-
const
|
|
219998
|
-
|
|
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) => {
|
|
220099
|
+
const dir = WAVE_ROUND_DIRS[input.round];
|
|
220100
|
+
const seatsDir = join(wavesDir, waveDir, WAVE_SEATS_DIR);
|
|
220101
|
+
const seats = waveRoundSeats(config.roles, input.round).map((role) => {
|
|
220005
220102
|
const bias = input.round === "judge" ? JUDGE_BIASES[(Number(role.slice(1)) - 1) % JUDGE_BIASES.length] : void 0;
|
|
220006
|
-
const file = `${wavesRel}/${waveDir}/${
|
|
220103
|
+
const file = `${wavesRel}/${waveDir}/${dir}/${role}.md`;
|
|
220104
|
+
const ticket = randomBytes(16).toString("hex");
|
|
220105
|
+
fs.write(join(seatsDir, role), `${seatTicketHash(ticket)}\n`);
|
|
220007
220106
|
const lines = [
|
|
220008
220107
|
SEAT_PRELUDE,
|
|
220009
220108
|
"",
|
|
220010
220109
|
ROLE_PROMPTS[input.round] ?? "",
|
|
220011
220110
|
"",
|
|
220111
|
+
`Perfil: ${WAVE_SEAT_PROFILE}`,
|
|
220012
220112
|
`Oleada: ${input.wave}. Brief: ${briefRel}.`,
|
|
220013
220113
|
`Escribe: ${file}.`,
|
|
220014
|
-
`
|
|
220114
|
+
`Ticket de asiento: ${ticket}. Es capacidad, no identidad: la ronda lo emitio para este asiento y WaveSubmit lo exige.`,
|
|
220115
|
+
`Entrega con WaveSubmit({ wave: "${input.wave}", round: "${input.round}", role: "${role}", ticket: "${ticket}", artifact: "..." }).`
|
|
220015
220116
|
];
|
|
220016
220117
|
if (bias !== void 0) lines.push(`Tu sesgo declarado es ${bias}: puntua CON el, no contra el.`);
|
|
220017
220118
|
return {
|
|
220018
220119
|
role,
|
|
220019
220120
|
file,
|
|
220121
|
+
ticket,
|
|
220020
220122
|
prompt: lines.join("\n")
|
|
220021
220123
|
};
|
|
220022
220124
|
});
|
|
@@ -220025,38 +220127,13 @@ function runWaveRoundForRoot(input) {
|
|
|
220025
220127
|
seats
|
|
220026
220128
|
};
|
|
220027
220129
|
}
|
|
220028
|
-
var ROUNDS;
|
|
220029
220130
|
var init_roundRunner = __esmMin((() => {
|
|
220030
220131
|
init_config$6();
|
|
220031
220132
|
init_fsJson();
|
|
220032
220133
|
init_nodeFs();
|
|
220134
|
+
init_wave$3();
|
|
220135
|
+
init_submitRunner();
|
|
220033
220136
|
init_prompts$2();
|
|
220034
|
-
ROUNDS = {
|
|
220035
|
-
propose: {
|
|
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
|
-
}
|
|
220059
|
-
};
|
|
220060
220137
|
}));
|
|
220061
220138
|
// ../../packages/agent-core-v2/src/features/wave/tools/round/round.md?raw
|
|
220062
220139
|
var round_default;
|
|
@@ -220112,111 +220189,17 @@ var init_submit$1 = __esmMin((() => {
|
|
|
220112
220189
|
]),
|
|
220113
220190
|
role: string().min(2),
|
|
220114
220191
|
artifact: string().min(1),
|
|
220192
|
+
ticket: string().optional(),
|
|
220193
|
+
reason: string().optional(),
|
|
220115
220194
|
replace: boolean$1().optional(),
|
|
220116
220195
|
root: string().optional()
|
|
220117
220196
|
}).strict();
|
|
220118
220197
|
IWaveSubmitTool = createDecorator("waveSubmitTool");
|
|
220119
220198
|
}));
|
|
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
|
-
}
|
|
220126
|
-
function findWaveDir(root, wavesRel, wave) {
|
|
220127
|
-
const fs = nodeWaveFs;
|
|
220128
|
-
const wavesDir = containedPath(root, wavesRel);
|
|
220129
|
-
const name = fs.list(wavesDir).filter((entry) => fs.isDirectory(join(wavesDir, entry))).find((entry) => entry === wave || entry.startsWith(`${wave}-`));
|
|
220130
|
-
return name === void 0 ? void 0 : join(wavesDir, name);
|
|
220131
|
-
}
|
|
220132
|
-
function runWaveSubmitForRoot(input) {
|
|
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
|
|
220147
|
-
};
|
|
220148
|
-
let base;
|
|
220149
|
-
try {
|
|
220150
|
-
base = findWaveDir(input.root, wavesRel, input.wave);
|
|
220151
|
-
} catch (error) {
|
|
220152
|
-
return {
|
|
220153
|
-
output: error instanceof Error ? error.message : String(error),
|
|
220154
|
-
isError: true
|
|
220155
|
-
};
|
|
220156
|
-
}
|
|
220157
|
-
if (base === void 0) return {
|
|
220158
|
-
output: `no existe la oleada ${input.wave} en ${wavesRel}`,
|
|
220159
|
-
isError: true
|
|
220160
|
-
};
|
|
220161
|
-
const dir = join(base, slot.dir);
|
|
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
|
|
220174
|
-
};
|
|
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
|
-
}
|
|
220178
|
-
var ROUND_SLOTS;
|
|
220179
|
-
var init_submitRunner = __esmMin((() => {
|
|
220180
|
-
init_config$6();
|
|
220181
|
-
init_fsJson();
|
|
220182
|
-
init_nodeFs();
|
|
220183
|
-
ROUND_SLOTS = {
|
|
220184
|
-
propose: {
|
|
220185
|
-
dir: "01-proposals",
|
|
220186
|
-
prefix: "P",
|
|
220187
|
-
role: "proponents"
|
|
220188
|
-
},
|
|
220189
|
-
defend: {
|
|
220190
|
-
dir: "02-defenses",
|
|
220191
|
-
prefix: "D",
|
|
220192
|
-
role: "defenders"
|
|
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
220199
|
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submit.md?raw
|
|
220217
220200
|
var submit_default;
|
|
220218
220201
|
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";
|
|
220202
|
+
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";
|
|
220220
220203
|
}));
|
|
220221
220204
|
// ../../packages/agent-core-v2/src/features/wave/tools/submit/submitTool.ts
|
|
220222
220205
|
var WaveSubmitTool;
|
|
@@ -220246,6 +220229,8 @@ var init_submitTool = __esmMin((() => {
|
|
|
220246
220229
|
round: args.round,
|
|
220247
220230
|
role: args.role,
|
|
220248
220231
|
artifact: args.artifact,
|
|
220232
|
+
ticket: args.ticket,
|
|
220233
|
+
reason: args.reason,
|
|
220249
220234
|
replace: args.replace
|
|
220250
220235
|
}))
|
|
220251
220236
|
};
|
|
@@ -220253,7 +220238,196 @@ var init_submitTool = __esmMin((() => {
|
|
|
220253
220238
|
};
|
|
220254
220239
|
WaveSubmitTool = __decorate([__decorateParam(0, ISessionContext)], WaveSubmitTool);
|
|
220255
220240
|
}));
|
|
220241
|
+
// ../../packages/agent-core-v2/src/features/wave/core/verify/runner.ts
|
|
220242
|
+
function splitCommand(command) {
|
|
220243
|
+
const tokens = [];
|
|
220244
|
+
let current = "";
|
|
220245
|
+
let quote;
|
|
220246
|
+
for (const char of command) {
|
|
220247
|
+
if (quote !== void 0) {
|
|
220248
|
+
if (char === quote) quote = void 0;
|
|
220249
|
+
else current += char;
|
|
220250
|
+
continue;
|
|
220251
|
+
}
|
|
220252
|
+
if (char === "\"" || char === "'") {
|
|
220253
|
+
quote = char;
|
|
220254
|
+
continue;
|
|
220255
|
+
}
|
|
220256
|
+
if (SHELL_METACHARACTERS.has(char)) throw new Error(`metacaracter de shell prohibido en: ${command}`);
|
|
220257
|
+
if (char === " " || char === " ") {
|
|
220258
|
+
if (current !== "") {
|
|
220259
|
+
tokens.push(current);
|
|
220260
|
+
current = "";
|
|
220261
|
+
}
|
|
220262
|
+
continue;
|
|
220263
|
+
}
|
|
220264
|
+
current += char;
|
|
220265
|
+
}
|
|
220266
|
+
if (quote !== void 0) throw new Error(`comillas sin cerrar en: ${command}`);
|
|
220267
|
+
if (current !== "") tokens.push(current);
|
|
220268
|
+
if (tokens.length === 0) throw new Error("comando vacio");
|
|
220269
|
+
return tokens;
|
|
220270
|
+
}
|
|
220271
|
+
function containPaths(argv, root) {
|
|
220272
|
+
for (const token of argv) {
|
|
220273
|
+
if (token.startsWith("-")) continue;
|
|
220274
|
+
if (!token.includes("/") && !/\.(mjs|cjs|js|ts|sh)$/.test(token)) continue;
|
|
220275
|
+
containedPath(root, token);
|
|
220276
|
+
}
|
|
220277
|
+
}
|
|
220278
|
+
function runCommand$2(command, options) {
|
|
220279
|
+
let argv;
|
|
220280
|
+
try {
|
|
220281
|
+
argv = splitCommand(command);
|
|
220282
|
+
const binary = (argv[0] ?? "").replace(/\.exe$/i, "");
|
|
220283
|
+
const allowed = options.allowBinaries.map((item) => item.replace(/\.exe$/i, ""));
|
|
220284
|
+
if (!allowed.includes(binary)) throw new Error(`binario no permitido: ${binary} (permitidos: ${allowed.join(", ")})`);
|
|
220285
|
+
containPaths(argv, options.root);
|
|
220286
|
+
} catch (error) {
|
|
220287
|
+
return {
|
|
220288
|
+
ok: false,
|
|
220289
|
+
output: `rechazado: ${error instanceof Error ? error.message : String(error)}`,
|
|
220290
|
+
rejected: true
|
|
220291
|
+
};
|
|
220292
|
+
}
|
|
220293
|
+
const result = spawnSync(argv[0] ?? "", argv.slice(1), {
|
|
220294
|
+
cwd: options.cwd ?? options.root,
|
|
220295
|
+
encoding: "utf8",
|
|
220296
|
+
timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS$1,
|
|
220297
|
+
stdio: "pipe",
|
|
220298
|
+
shell: false
|
|
220299
|
+
});
|
|
220300
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}${result.error === void 0 ? "" : result.error.message}`.replaceAll(/\s+/g, " ").trim().slice(0, 300);
|
|
220301
|
+
if (result.error !== void 0) return {
|
|
220302
|
+
ok: false,
|
|
220303
|
+
output: `no se pudo ejecutar: ${output}`,
|
|
220304
|
+
rejected: false
|
|
220305
|
+
};
|
|
220306
|
+
return {
|
|
220307
|
+
ok: result.status === 0,
|
|
220308
|
+
output,
|
|
220309
|
+
rejected: false,
|
|
220310
|
+
status: result.status ?? void 0
|
|
220311
|
+
};
|
|
220312
|
+
}
|
|
220313
|
+
function exitDetail(outcome) {
|
|
220314
|
+
return outcome.status === void 0 ? outcome.output : `exit ${outcome.status}: ${outcome.output}`;
|
|
220315
|
+
}
|
|
220316
|
+
function evaluateMutant(ac, verifyCommand, options) {
|
|
220317
|
+
const script = asText$1(asRecord$2(ac["falsifier"])["script"]);
|
|
220318
|
+
if (script === "") return {
|
|
220319
|
+
state: "declarado",
|
|
220320
|
+
detail: "sin falsifier.script: el AC queda declarado y cuenta como FALLO"
|
|
220321
|
+
};
|
|
220322
|
+
const acId = asText$1(ac["id"]);
|
|
220323
|
+
const apply = runCommand$2(`${script} apply`, options);
|
|
220324
|
+
if (apply.rejected) return {
|
|
220325
|
+
state: "rechazado",
|
|
220326
|
+
detail: `apply rechazado (${script}, ${acId}): ${apply.output}`
|
|
220327
|
+
};
|
|
220328
|
+
let mutated;
|
|
220329
|
+
let restore;
|
|
220330
|
+
try {
|
|
220331
|
+
if (apply.ok) mutated = runCommand$2(verifyCommand, options);
|
|
220332
|
+
} finally {
|
|
220333
|
+
restore = runCommand$2(`${script} restore`, options);
|
|
220334
|
+
}
|
|
220335
|
+
const failures = [];
|
|
220336
|
+
if (!apply.ok) failures.push(`apply fallo (${script}, ${acId}) ${exitDetail(apply)}`);
|
|
220337
|
+
if (restore.rejected || !restore.ok) failures.push(`restore fallo (${script}, ${acId}), el arbol puede estar sucio: ${restore.output}`);
|
|
220338
|
+
if (failures.length > 0) return {
|
|
220339
|
+
state: "error",
|
|
220340
|
+
detail: failures.join(" · ")
|
|
220341
|
+
};
|
|
220342
|
+
if (mutated === void 0) return {
|
|
220343
|
+
state: "error",
|
|
220344
|
+
detail: `no se ejecuto el verify con la mutacion de ${acId}`
|
|
220345
|
+
};
|
|
220346
|
+
if (mutated.ok) return {
|
|
220347
|
+
state: "sobrevive",
|
|
220348
|
+
detail: "el verify pasa con la mutacion aplicada: el AC no muerde"
|
|
220349
|
+
};
|
|
220350
|
+
if (!runCommand$2(verifyCommand, options).ok) return {
|
|
220351
|
+
state: "error",
|
|
220352
|
+
detail: "el verify no vuelve a verde tras restaurar"
|
|
220353
|
+
};
|
|
220354
|
+
return {
|
|
220355
|
+
state: "muerto",
|
|
220356
|
+
detail: "rojo con la mutacion, verde tras restaurar"
|
|
220357
|
+
};
|
|
220358
|
+
}
|
|
220359
|
+
function selectTaskCriteria(fs, root, cfg, taskId, ac) {
|
|
220360
|
+
const tasksDir = containedPath(root, cfg.layout.backlog);
|
|
220361
|
+
const file = walk$1(fs, join(tasksDir, "tasks"), (path) => path.endsWith(`${taskId}.json`))[0];
|
|
220362
|
+
if (file === void 0) throw new Error(`no encuentro la task ${taskId} en ${cfg.layout.backlog}/tasks/`);
|
|
220363
|
+
const criteria = asArray$2(asRecord$2(readJson$2(fs, file))["ac"]).map(asRecord$2);
|
|
220364
|
+
if (ac === void 0) return {
|
|
220365
|
+
taskId,
|
|
220366
|
+
criteria
|
|
220367
|
+
};
|
|
220368
|
+
const selected = criteria.filter((entry) => asText$1(entry["id"]) === ac);
|
|
220369
|
+
if (selected.length === 0) throw new Error(`no existe el criterio ${ac} en la task ${taskId}`);
|
|
220370
|
+
return {
|
|
220371
|
+
taskId,
|
|
220372
|
+
criteria: selected
|
|
220373
|
+
};
|
|
220374
|
+
}
|
|
220375
|
+
function verifyTask(fs, root, cfg, taskId, options) {
|
|
220376
|
+
const { criteria } = selectTaskCriteria(fs, root, cfg, taskId, options?.ac);
|
|
220377
|
+
const runOptions = {
|
|
220378
|
+
root,
|
|
220379
|
+
allowBinaries: cfg.vocabulary.verifyCommands,
|
|
220380
|
+
cwd: options?.cwd,
|
|
220381
|
+
timeoutMs: options?.timeoutMs
|
|
220382
|
+
};
|
|
220383
|
+
const acs = [];
|
|
220384
|
+
let declared = 0;
|
|
220385
|
+
for (const ac of criteria) {
|
|
220386
|
+
const verifyCommand = asText$1(ac["verify"]);
|
|
220387
|
+
const verify = runCommand$2(verifyCommand, runOptions);
|
|
220388
|
+
const mutant = evaluateMutant(ac, verifyCommand, runOptions);
|
|
220389
|
+
if (mutant.state === "declarado") declared++;
|
|
220390
|
+
const declaredOk = options?.allowDeclared === true && mutant.state === "declarado";
|
|
220391
|
+
const ok = verify.ok && (mutant.state === "muerto" || declaredOk);
|
|
220392
|
+
acs.push({
|
|
220393
|
+
acId: asText$1(ac["id"]),
|
|
220394
|
+
verify,
|
|
220395
|
+
mutant,
|
|
220396
|
+
ok
|
|
220397
|
+
});
|
|
220398
|
+
}
|
|
220399
|
+
return {
|
|
220400
|
+
taskId,
|
|
220401
|
+
acs,
|
|
220402
|
+
declared,
|
|
220403
|
+
ok: acs.length > 0 && acs.every((ac) => ac.ok)
|
|
220404
|
+
};
|
|
220405
|
+
}
|
|
220406
|
+
var SHELL_METACHARACTERS, DEFAULT_TIMEOUT_MS$1;
|
|
220407
|
+
var init_runner = __esmMin((() => {
|
|
220408
|
+
init_config$6();
|
|
220409
|
+
init_fsJson();
|
|
220410
|
+
SHELL_METACHARACTERS = /* @__PURE__ */ new Set([
|
|
220411
|
+
"|",
|
|
220412
|
+
"&",
|
|
220413
|
+
";",
|
|
220414
|
+
"<",
|
|
220415
|
+
">",
|
|
220416
|
+
"`",
|
|
220417
|
+
"$",
|
|
220418
|
+
"\n",
|
|
220419
|
+
"\r"
|
|
220420
|
+
]);
|
|
220421
|
+
DEFAULT_TIMEOUT_MS$1 = 6e5;
|
|
220422
|
+
}));
|
|
220256
220423
|
// ../../packages/agent-core-v2/src/features/wave/core/gate/checks.ts
|
|
220424
|
+
function measurableThreshold(text, units) {
|
|
220425
|
+
const low = normalize$1(text);
|
|
220426
|
+
if (OPERATOR_WITH_NUMBER.test(low)) return true;
|
|
220427
|
+
if (EXACT_VALUE.test(low)) return true;
|
|
220428
|
+
if (units.some((unit) => new RegExp(`\\d\\s*${escapeRegExp$1(unit)}\\b`).test(low))) return true;
|
|
220429
|
+
return low.split(/\s*(?:,|;|\by\b)\s*/).filter(Boolean).length >= 3;
|
|
220430
|
+
}
|
|
220257
220431
|
function record$1(value) {
|
|
220258
220432
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
220259
220433
|
}
|
|
@@ -220281,38 +220455,350 @@ function walk(fs, dir, accept, acc = []) {
|
|
|
220281
220455
|
}
|
|
220282
220456
|
return acc;
|
|
220283
220457
|
}
|
|
220284
|
-
function
|
|
220285
|
-
|
|
220458
|
+
function requiredArtifacts(cfg) {
|
|
220459
|
+
const required = ["00-brief.md"];
|
|
220460
|
+
for (const round of WAVE_ROUNDS) for (const seat of waveRoundSeats(cfg.roles, round)) required.push(`${WAVE_ROUND_DIRS[round]}/${seat}.md`);
|
|
220461
|
+
required.push(DECISION_FILE, "07-epics.json");
|
|
220462
|
+
return required;
|
|
220463
|
+
}
|
|
220464
|
+
function briefSections(text) {
|
|
220465
|
+
const sections = [];
|
|
220466
|
+
let current;
|
|
220467
|
+
for (const line of text.split("\n")) {
|
|
220468
|
+
const heading = /^##\s+(.+?)\s*$/.exec(line);
|
|
220469
|
+
if (heading !== null) {
|
|
220470
|
+
current = {
|
|
220471
|
+
title: heading[1] ?? "",
|
|
220472
|
+
body: []
|
|
220473
|
+
};
|
|
220474
|
+
sections.push(current);
|
|
220475
|
+
continue;
|
|
220476
|
+
}
|
|
220477
|
+
if (/^#\s+/.test(line)) {
|
|
220478
|
+
current = void 0;
|
|
220479
|
+
continue;
|
|
220480
|
+
}
|
|
220481
|
+
current?.body.push(line);
|
|
220482
|
+
}
|
|
220483
|
+
return sections.map((section) => ({
|
|
220484
|
+
title: section.title,
|
|
220485
|
+
body: section.body.join("\n").trim()
|
|
220486
|
+
}));
|
|
220286
220487
|
}
|
|
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);
|
|
220488
|
+
function sectionKeyword(title) {
|
|
220489
|
+
return normalize$1(title).replace(/^\d+\.?\s*/, "").match(/[a-z0-9]+/)?.[0] ?? "";
|
|
220291
220490
|
}
|
|
220292
|
-
function
|
|
220293
|
-
return
|
|
220491
|
+
function decisionStrip(value) {
|
|
220492
|
+
return (value ?? "").replaceAll("*", "").trim();
|
|
220294
220493
|
}
|
|
220295
|
-
function
|
|
220296
|
-
|
|
220297
|
-
return resolved.startsWith(waveDir) && existsSync(resolved);
|
|
220494
|
+
function decisionSplitRow(line) {
|
|
220495
|
+
return line.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((cell) => cell.trim());
|
|
220298
220496
|
}
|
|
220299
|
-
function
|
|
220300
|
-
|
|
220301
|
-
|
|
220302
|
-
|
|
220303
|
-
|
|
220304
|
-
|
|
220497
|
+
function isDecisionSeparator(row) {
|
|
220498
|
+
return row.length > 0 && row.every((cell) => DECISION_SEPARATOR.test(decisionStrip(cell)));
|
|
220499
|
+
}
|
|
220500
|
+
function decisionTables(text) {
|
|
220501
|
+
const blocks = [];
|
|
220502
|
+
let current = [];
|
|
220503
|
+
for (const line of text.split("\n")) {
|
|
220504
|
+
if (line.trim().startsWith("|")) {
|
|
220505
|
+
current.push(decisionSplitRow(line));
|
|
220506
|
+
continue;
|
|
220507
|
+
}
|
|
220508
|
+
if (current.length > 0) blocks.push(current);
|
|
220509
|
+
current = [];
|
|
220305
220510
|
}
|
|
220306
|
-
|
|
220511
|
+
if (current.length > 0) blocks.push(current);
|
|
220512
|
+
return blocks.filter((block) => block.length >= 2).map((block) => ({
|
|
220513
|
+
header: block[0] ?? [],
|
|
220514
|
+
body: block.slice(1).filter((row) => !isDecisionSeparator(row) && row.length === (block[0] ?? []).length)
|
|
220515
|
+
}));
|
|
220307
220516
|
}
|
|
220308
|
-
function
|
|
220309
|
-
const
|
|
220310
|
-
|
|
220311
|
-
|
|
220312
|
-
|
|
220313
|
-
|
|
220314
|
-
|
|
220315
|
-
|
|
220517
|
+
function decisionNumber(cell) {
|
|
220518
|
+
const value = decisionStrip(cell);
|
|
220519
|
+
if (value === "") return void 0;
|
|
220520
|
+
const match = DECISION_LEADING_NUMBER.exec(value);
|
|
220521
|
+
return match === null ? void 0 : Number(match[0].replace(",", "."));
|
|
220522
|
+
}
|
|
220523
|
+
function decisionProposal(cell) {
|
|
220524
|
+
const value = decisionStrip(cell);
|
|
220525
|
+
if (value === "") return void 0;
|
|
220526
|
+
return DECISION_PROPOSAL.test(value.toLowerCase()) ? value.toUpperCase() : void 0;
|
|
220527
|
+
}
|
|
220528
|
+
function decisionAxis(row, axes) {
|
|
220529
|
+
const low = normalize$1(decisionStrip(row));
|
|
220530
|
+
if (low === "") return void 0;
|
|
220531
|
+
const exact = axes.find((axis) => normalize$1(axis) === low);
|
|
220532
|
+
if (exact !== void 0) return exact;
|
|
220533
|
+
return axes.find((axis) => low.includes(normalize$1(axis)));
|
|
220534
|
+
}
|
|
220535
|
+
function isDecisionTotal(cell) {
|
|
220536
|
+
return /\btotal\b/.test(normalize$1(decisionStrip(cell)));
|
|
220537
|
+
}
|
|
220538
|
+
function isDecisionMedian(cell) {
|
|
220539
|
+
return /\bmedian/.test(normalize$1(decisionStrip(cell)));
|
|
220540
|
+
}
|
|
220541
|
+
function decisionColumn(header, predicate) {
|
|
220542
|
+
return header.findIndex((cell) => predicate(cell));
|
|
220543
|
+
}
|
|
220544
|
+
function findDecisionMatrix(blocks, axes) {
|
|
220545
|
+
let best;
|
|
220546
|
+
for (const block of blocks) {
|
|
220547
|
+
const header = block.header.map(decisionStrip);
|
|
220548
|
+
const columnProposals = header.filter((cell) => decisionProposal(cell) !== void 0);
|
|
220549
|
+
const rowProposals = block.body.filter((row) => decisionProposal(row[0]) !== void 0);
|
|
220550
|
+
const axisColumns = header.filter((cell) => decisionAxis(cell, axes) !== void 0 && !isDecisionTotal(cell) && !isDecisionMedian(cell));
|
|
220551
|
+
const axisRows = block.body.filter((row) => decisionAxis(row[0], axes) !== void 0);
|
|
220552
|
+
const byColumn = columnProposals.length >= 2 && axisRows.length > 0;
|
|
220553
|
+
const byRow = rowProposals.length >= 2 && axisColumns.length > 0;
|
|
220554
|
+
if (!byColumn && !byRow) continue;
|
|
220555
|
+
const score = Math.max(axisRows.length, axisColumns.length) * 10 + Math.max(columnProposals.length, rowProposals.length);
|
|
220556
|
+
if (best === void 0 || score > best.score) best = {
|
|
220557
|
+
block,
|
|
220558
|
+
orientation: byColumn ? "columns" : "rows",
|
|
220559
|
+
score
|
|
220560
|
+
};
|
|
220561
|
+
}
|
|
220562
|
+
return best;
|
|
220563
|
+
}
|
|
220564
|
+
function readDecisionColumns(block, axes, proposals, found) {
|
|
220565
|
+
const indexes = /* @__PURE__ */ new Map();
|
|
220566
|
+
for (const [index, cell] of block.header.entries()) {
|
|
220567
|
+
const proposal = decisionProposal(cell);
|
|
220568
|
+
if (proposal !== void 0 && !indexes.has(proposal)) indexes.set(proposal, index);
|
|
220569
|
+
}
|
|
220570
|
+
for (const row of block.body) {
|
|
220571
|
+
const axis = decisionAxis(row[0], axes);
|
|
220572
|
+
if (axis === void 0 || found.has(axis)) continue;
|
|
220573
|
+
const cells = {};
|
|
220574
|
+
found.set(axis, {
|
|
220575
|
+
label: decisionStrip(row[0]),
|
|
220576
|
+
cells
|
|
220577
|
+
});
|
|
220578
|
+
for (const proposal of proposals) {
|
|
220579
|
+
const index = indexes.get(proposal);
|
|
220580
|
+
cells[proposal] = index === void 0 ? void 0 : decisionNumber(row[index]);
|
|
220581
|
+
}
|
|
220582
|
+
}
|
|
220583
|
+
return indexes;
|
|
220584
|
+
}
|
|
220585
|
+
function readDecisionRows(block, axes, found) {
|
|
220586
|
+
const columns = [];
|
|
220587
|
+
for (const [index, cell] of block.header.entries()) {
|
|
220588
|
+
const axis = decisionAxis(cell, axes);
|
|
220589
|
+
if (axis === void 0 || isDecisionTotal(cell) || isDecisionMedian(cell)) continue;
|
|
220590
|
+
columns.push({
|
|
220591
|
+
axis,
|
|
220592
|
+
index,
|
|
220593
|
+
label: decisionStrip(cell)
|
|
220594
|
+
});
|
|
220595
|
+
}
|
|
220596
|
+
const seen = [];
|
|
220597
|
+
for (const row of block.body) {
|
|
220598
|
+
const proposal = decisionProposal(row[0]);
|
|
220599
|
+
if (proposal === void 0) continue;
|
|
220600
|
+
if (!seen.includes(proposal)) seen.push(proposal);
|
|
220601
|
+
for (const column of columns) {
|
|
220602
|
+
const existing = found.get(column.axis);
|
|
220603
|
+
const entry = existing ?? {
|
|
220604
|
+
label: column.label,
|
|
220605
|
+
cells: {}
|
|
220606
|
+
};
|
|
220607
|
+
if (existing === void 0) found.set(column.axis, entry);
|
|
220608
|
+
if (entry.cells[proposal] !== void 0) continue;
|
|
220609
|
+
entry.cells[proposal] = decisionNumber(row[column.index]);
|
|
220610
|
+
}
|
|
220611
|
+
}
|
|
220612
|
+
return seen;
|
|
220613
|
+
}
|
|
220614
|
+
function decisionDeclarations(blocks, matrix, proposals) {
|
|
220615
|
+
const totals = {};
|
|
220616
|
+
const medians = {};
|
|
220617
|
+
const take = (target, proposal, value) => {
|
|
220618
|
+
if (proposal === void 0 || value === void 0 || target[proposal] !== void 0) return;
|
|
220619
|
+
target[proposal] = value;
|
|
220620
|
+
};
|
|
220621
|
+
if (matrix !== void 0) {
|
|
220622
|
+
const header = matrix.block.header.map(decisionStrip);
|
|
220623
|
+
const totalColumn = matrix.orientation === "rows" ? decisionColumn(header, isDecisionTotal) : -1;
|
|
220624
|
+
const medianColumn = matrix.orientation === "rows" ? decisionColumn(header, isDecisionMedian) : -1;
|
|
220625
|
+
for (const row of matrix.block.body) {
|
|
220626
|
+
const proposal = decisionProposal(row[0]);
|
|
220627
|
+
if (proposal !== void 0) {
|
|
220628
|
+
if (totalColumn !== -1) take(totals, proposal, decisionNumber(row[totalColumn]));
|
|
220629
|
+
if (medianColumn !== -1) take(medians, proposal, decisionNumber(row[medianColumn]));
|
|
220630
|
+
continue;
|
|
220631
|
+
}
|
|
220632
|
+
if (isDecisionTotal(row[0]) || isDecisionMedian(row[0])) {
|
|
220633
|
+
const target = isDecisionTotal(row[0]) ? totals : medians;
|
|
220634
|
+
for (const item of proposals) {
|
|
220635
|
+
const index = header.findIndex((cell) => decisionProposal(cell) === item);
|
|
220636
|
+
take(target, item, index === -1 ? void 0 : decisionNumber(row[index]));
|
|
220637
|
+
}
|
|
220638
|
+
}
|
|
220639
|
+
}
|
|
220640
|
+
}
|
|
220641
|
+
for (const block of blocks) {
|
|
220642
|
+
const header = block.header.map(decisionStrip);
|
|
220643
|
+
const totalColumn = decisionColumn(header, isDecisionTotal);
|
|
220644
|
+
const medianColumn = decisionColumn(header, isDecisionMedian);
|
|
220645
|
+
if (totalColumn === -1 && medianColumn === -1) continue;
|
|
220646
|
+
for (const row of block.body) {
|
|
220647
|
+
const proposal = decisionProposal(row[0]);
|
|
220648
|
+
if (proposal === void 0) continue;
|
|
220649
|
+
if (totalColumn !== -1) take(totals, proposal, decisionNumber(row[totalColumn]));
|
|
220650
|
+
if (medianColumn !== -1) take(medians, proposal, decisionNumber(row[medianColumn]));
|
|
220651
|
+
}
|
|
220652
|
+
}
|
|
220653
|
+
return {
|
|
220654
|
+
totals,
|
|
220655
|
+
medians
|
|
220656
|
+
};
|
|
220657
|
+
}
|
|
220658
|
+
function decisionMargins(blocks) {
|
|
220659
|
+
for (const block of blocks) {
|
|
220660
|
+
const header = block.header.map(decisionStrip);
|
|
220661
|
+
const judgeColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("juez"));
|
|
220662
|
+
const marginColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("margen"));
|
|
220663
|
+
if (judgeColumn === -1 || marginColumn === -1) continue;
|
|
220664
|
+
const preferColumn = decisionColumn(header, (cell) => normalize$1(cell).includes("prefer"));
|
|
220665
|
+
const rows = [];
|
|
220666
|
+
for (const row of block.body) {
|
|
220667
|
+
const judge = decisionStrip(row[judgeColumn]);
|
|
220668
|
+
if (!DECISION_JUDGE.test(judge)) continue;
|
|
220669
|
+
const margin = DECISION_SIGNED_MARGIN.exec(decisionStrip(row[marginColumn]));
|
|
220670
|
+
if (margin === null) continue;
|
|
220671
|
+
rows.push({
|
|
220672
|
+
judge,
|
|
220673
|
+
margin: Number((margin[1] ?? "0").replace(",", ".")),
|
|
220674
|
+
prefers: preferColumn === -1 ? void 0 : decisionProposal(row[preferColumn])
|
|
220675
|
+
});
|
|
220676
|
+
}
|
|
220677
|
+
if (rows.length > 0) return rows;
|
|
220678
|
+
}
|
|
220679
|
+
return [];
|
|
220680
|
+
}
|
|
220681
|
+
function decisionDissent(text) {
|
|
220682
|
+
const lines = text.split("\n");
|
|
220683
|
+
const start = lines.findIndex((line) => /^#{1,3}\s+\d*\.?\s*disidencias/i.test(line));
|
|
220684
|
+
if (start === -1) return void 0;
|
|
220685
|
+
const level = /^(#{1,3})/.exec(lines[start] ?? "")?.[1]?.length ?? 1;
|
|
220686
|
+
const collected = [];
|
|
220687
|
+
for (const line of lines.slice(start + 1)) {
|
|
220688
|
+
const heading = /^(#{1,3})\s+\S/.exec(line);
|
|
220689
|
+
if (heading !== null && (heading[1] ?? "").length <= level) break;
|
|
220690
|
+
collected.push(line);
|
|
220691
|
+
}
|
|
220692
|
+
return collected.join("\n").trim();
|
|
220693
|
+
}
|
|
220694
|
+
function parseDecisionMatrix(text, options) {
|
|
220695
|
+
const axes = options.axes.map(String);
|
|
220696
|
+
const blocks = decisionTables(text);
|
|
220697
|
+
const matrix = findDecisionMatrix(blocks, axes);
|
|
220698
|
+
const found = /* @__PURE__ */ new Map();
|
|
220699
|
+
let proposals = options.proposals.map(String);
|
|
220700
|
+
let present = [];
|
|
220701
|
+
if (matrix !== void 0) {
|
|
220702
|
+
if (matrix.orientation === "columns") {
|
|
220703
|
+
if (proposals.length === 0) proposals = matrix.block.header.map(decisionStrip).map(decisionProposal).filter((label) => label !== void 0);
|
|
220704
|
+
const indexes = readDecisionColumns(matrix.block, axes, proposals, found);
|
|
220705
|
+
present = proposals.filter((proposal) => indexes.has(proposal));
|
|
220706
|
+
} else {
|
|
220707
|
+
if (proposals.length === 0) proposals = matrix.block.body.map((row) => decisionProposal(row[0])).filter((label) => label !== void 0);
|
|
220708
|
+
const seen = readDecisionRows(matrix.block, axes, found);
|
|
220709
|
+
present = proposals.filter((proposal) => seen.includes(proposal));
|
|
220710
|
+
}
|
|
220711
|
+
}
|
|
220712
|
+
const axisRows = [];
|
|
220713
|
+
const cells = [];
|
|
220714
|
+
const missing = [];
|
|
220715
|
+
for (const axis of axes) {
|
|
220716
|
+
const row = found.get(axis);
|
|
220717
|
+
if (row === void 0) continue;
|
|
220718
|
+
axisRows.push({
|
|
220719
|
+
axis,
|
|
220720
|
+
label: row.label,
|
|
220721
|
+
cells: row.cells
|
|
220722
|
+
});
|
|
220723
|
+
for (const proposal of present) {
|
|
220724
|
+
const value = row.cells[proposal];
|
|
220725
|
+
if (typeof value === "number") cells.push({
|
|
220726
|
+
axis,
|
|
220727
|
+
proposal,
|
|
220728
|
+
value
|
|
220729
|
+
});
|
|
220730
|
+
else missing.push({
|
|
220731
|
+
axis,
|
|
220732
|
+
proposal
|
|
220733
|
+
});
|
|
220734
|
+
}
|
|
220735
|
+
}
|
|
220736
|
+
const declarations = decisionDeclarations(blocks, matrix, proposals);
|
|
220737
|
+
const axesFound = axisRows.map((row) => row.axis);
|
|
220738
|
+
return {
|
|
220739
|
+
present: matrix !== void 0,
|
|
220740
|
+
orientation: matrix?.orientation,
|
|
220741
|
+
header: matrix === void 0 ? [] : matrix.block.header.map(decisionStrip),
|
|
220742
|
+
proposals,
|
|
220743
|
+
presentProposals: present,
|
|
220744
|
+
axisRows,
|
|
220745
|
+
cells,
|
|
220746
|
+
missing,
|
|
220747
|
+
axesFound,
|
|
220748
|
+
axesMissing: axes.filter((axis) => !axesFound.includes(axis)),
|
|
220749
|
+
totals: declarations.totals,
|
|
220750
|
+
medians: declarations.medians,
|
|
220751
|
+
margins: decisionMargins(blocks),
|
|
220752
|
+
dissent: decisionDissent(text)
|
|
220753
|
+
};
|
|
220754
|
+
}
|
|
220755
|
+
function decisionProposalSum(matrix, proposal) {
|
|
220756
|
+
const values = matrix.axisRows.map((row) => row.cells[proposal]);
|
|
220757
|
+
if (values.length === 0) return void 0;
|
|
220758
|
+
let total = 0;
|
|
220759
|
+
for (const value of values) {
|
|
220760
|
+
if (typeof value !== "number") return void 0;
|
|
220761
|
+
total += value;
|
|
220762
|
+
}
|
|
220763
|
+
return total;
|
|
220764
|
+
}
|
|
220765
|
+
function decisionMedian(values) {
|
|
220766
|
+
if (values.length === 0) return void 0;
|
|
220767
|
+
const sorted = [...values].toSorted((left, right) => left - right);
|
|
220768
|
+
const middle = Math.floor(sorted.length / 2);
|
|
220769
|
+
const current = sorted[middle];
|
|
220770
|
+
if (current === void 0) return void 0;
|
|
220771
|
+
if (sorted.length % 2 === 1) return current;
|
|
220772
|
+
const previous = sorted[middle - 1];
|
|
220773
|
+
return previous === void 0 ? void 0 : (previous + current) / 2;
|
|
220774
|
+
}
|
|
220775
|
+
function decisionRecalculateMedians(verdicts, options) {
|
|
220776
|
+
const tables = [];
|
|
220777
|
+
const missing = [];
|
|
220778
|
+
for (const verdict of verdicts) {
|
|
220779
|
+
const matrix = parseDecisionMatrix(verdict.text, options);
|
|
220780
|
+
if (!(matrix.present && matrix.axesMissing.length === 0 && matrix.missing.length === 0)) {
|
|
220781
|
+
missing.push(verdict.file);
|
|
220782
|
+
continue;
|
|
220783
|
+
}
|
|
220784
|
+
const totals = {};
|
|
220785
|
+
for (const proposal of matrix.proposals) totals[proposal] = decisionProposalSum(matrix, proposal) ?? NaN;
|
|
220786
|
+
tables.push({
|
|
220787
|
+
file: verdict.file,
|
|
220788
|
+
totals
|
|
220789
|
+
});
|
|
220790
|
+
}
|
|
220791
|
+
const medians = {};
|
|
220792
|
+
if (missing.length === 0 && tables.length > 0) for (const proposal of options.proposals) {
|
|
220793
|
+
const values = tables.map((entry) => entry.totals[proposal]).filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
220794
|
+
if (values.length !== tables.length) continue;
|
|
220795
|
+
const value = decisionMedian(values);
|
|
220796
|
+
if (value !== void 0) medians[proposal] = value;
|
|
220797
|
+
}
|
|
220798
|
+
return {
|
|
220799
|
+
medians,
|
|
220800
|
+
missing
|
|
220801
|
+
};
|
|
220316
220802
|
}
|
|
220317
220803
|
function runWaveGate(fs, root, cfg) {
|
|
220318
220804
|
const findings = [];
|
|
@@ -220341,8 +220827,24 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220341
220827
|
let epics = [];
|
|
220342
220828
|
let tasks = [];
|
|
220343
220829
|
let totalAc = 0;
|
|
220830
|
+
const state = waveConfigState(cfg);
|
|
220344
220831
|
block("config", () => {
|
|
220345
220832
|
if (cfg.loadedFrom === void 0) add("config.missing", null, "no se encontro workflow.config.json");
|
|
220833
|
+
const raw = state.raw;
|
|
220834
|
+
const version = typeof raw["version"] === "number" ? raw["version"] : state.version;
|
|
220835
|
+
for (const key of [
|
|
220836
|
+
"version",
|
|
220837
|
+
"layout",
|
|
220838
|
+
"waves",
|
|
220839
|
+
"thresholds",
|
|
220840
|
+
"vocabulary"
|
|
220841
|
+
]) if (raw[key] === void 0) add("config.missing_key", null, `falta la clave "${key}"`);
|
|
220842
|
+
if (version !== 1 && version !== 2) add("config.version_unknown", null, `version "${String(version)}" fuera de uno y dos: el gate no sabe leerla`);
|
|
220843
|
+
if (version === 2) {
|
|
220844
|
+
if (raw["wavesOpen"] === void 0) add("config.missing_key", null, "falta la clave \"wavesOpen\"");
|
|
220845
|
+
if (raw["vocabulary"] === void 0 || record$1(raw["vocabulary"])["units"] === void 0) add("config.missing_key", null, "falta la clave \"vocabulary.units\"");
|
|
220846
|
+
if (raw["falsifier"] === void 0) add("config.missing_key", null, "falta la clave \"falsifier\"");
|
|
220847
|
+
}
|
|
220346
220848
|
if (cfg.waves.length === 0) add("config.bad_waves", null, "waves debe ser un array no vacio");
|
|
220347
220849
|
if (vocabulary.verifyCommands.length === 0) add("config.bad_vocabulary", null, "vocabulary.verifyCommands vacio");
|
|
220348
220850
|
if (vocabulary.verifyPrefixes.length === 0) add("config.bad_vocabulary", null, "vocabulary.verifyPrefixes vacio");
|
|
@@ -220378,19 +220880,89 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220378
220880
|
}
|
|
220379
220881
|
}
|
|
220380
220882
|
});
|
|
220883
|
+
block("brief", () => {
|
|
220884
|
+
const templateFile = join(root, BRIEF_TEMPLATE);
|
|
220885
|
+
if (!fs.exists(templateFile)) return;
|
|
220886
|
+
const template = briefSections(fs.read(templateFile) ?? "");
|
|
220887
|
+
if (wavesDir === void 0 || !fs.isDirectory(wavesDir)) return;
|
|
220888
|
+
for (const wave of cfg.waves) {
|
|
220889
|
+
const match = waveDirs.find((name) => name === wave || name.startsWith(`${wave}-`));
|
|
220890
|
+
if (match === void 0) continue;
|
|
220891
|
+
const file = join(wavesDir, match, "00-brief.md");
|
|
220892
|
+
const text = fs.read(file);
|
|
220893
|
+
if (text === void 0) continue;
|
|
220894
|
+
const at = relative$1(root, file);
|
|
220895
|
+
const sections = briefSections(text);
|
|
220896
|
+
if (sections.length !== template.length) add("waves.brief_template_drift", at, `${sections.length} secciones frente a ${template.length} de ${BRIEF_TEMPLATE}: el brief ya no sigue la plantilla`);
|
|
220897
|
+
for (const [index, expected] of template.entries()) {
|
|
220898
|
+
const section = sections[index];
|
|
220899
|
+
if (section === void 0) continue;
|
|
220900
|
+
if (sectionKeyword(section.title) !== sectionKeyword(expected.title)) add("waves.brief_template_drift", at, `la seccion ${index + 1} se titula "${section.title}" y ${BRIEF_TEMPLATE} exige "${expected.title}"`);
|
|
220901
|
+
}
|
|
220902
|
+
for (const section of sections) if (section.body === "") add("waves.brief_empty_section", at, `la seccion "${section.title}" no tiene contenido`);
|
|
220903
|
+
}
|
|
220904
|
+
});
|
|
220381
220905
|
block("decision", () => {
|
|
220382
220906
|
const dir = wavesDir;
|
|
220383
220907
|
if (dir === void 0 || !fs.isDirectory(dir)) return;
|
|
220908
|
+
const axes = cfg.quorum.axes;
|
|
220909
|
+
const proposals = Array.from({ length: cfg.roles.proponents }, (_, index) => `P${index + 1}`);
|
|
220910
|
+
const judges = cfg.roles.judges;
|
|
220384
220911
|
for (const wave of cfg.waves) {
|
|
220385
220912
|
const match = waveDirs.find((name) => name === wave || name.startsWith(`${wave}-`));
|
|
220386
220913
|
if (match === void 0) continue;
|
|
220387
|
-
const
|
|
220914
|
+
const base = join(dir, match);
|
|
220915
|
+
const file = join(base, DECISION_FILE);
|
|
220388
220916
|
const text = fs.read(file);
|
|
220389
220917
|
if (text === void 0) continue;
|
|
220390
220918
|
const low = normalize$1(text);
|
|
220391
220919
|
const at = relative$1(root, file);
|
|
220392
|
-
|
|
220393
|
-
|
|
220920
|
+
const matrix = parseDecisionMatrix(text, {
|
|
220921
|
+
axes,
|
|
220922
|
+
proposals
|
|
220923
|
+
});
|
|
220924
|
+
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`);
|
|
220925
|
+
if (!matrix.present) add("waves.decision_without_quorum", at, "sin tabla de la matriz: la ronda no trae puntuaciones que auditar");
|
|
220926
|
+
else {
|
|
220927
|
+
for (const axis of axes) if (!matrix.axesFound.includes(axis)) add("waves.decision_missing_axis", at, `sin eje "${axis}" en la matriz`);
|
|
220928
|
+
for (const item of matrix.missing) add("waves.decision_matrix_incomplete", at, `eje "${item.axis}" · propuesta ${item.proposal}: celda vacia`);
|
|
220929
|
+
for (const proposal of proposals) {
|
|
220930
|
+
const declared = matrix.totals[proposal];
|
|
220931
|
+
const sum = decisionProposalSum(matrix, proposal);
|
|
220932
|
+
if (declared === void 0 || sum === void 0 || declared === sum) continue;
|
|
220933
|
+
add("waves.decision_total_mismatch", at, `${proposal}: total declarado ${declared} y recalculado ${sum} desde las celdas de la matriz`);
|
|
220934
|
+
}
|
|
220935
|
+
if (proposals.some((proposal) => matrix.medians[proposal] !== void 0)) {
|
|
220936
|
+
const verdictsDir = join(base, "04-verdicts");
|
|
220937
|
+
const recalc = decisionRecalculateMedians(Array.from({ length: judges }, (_, index) => {
|
|
220938
|
+
const name = `J${index + 1}.md`;
|
|
220939
|
+
return {
|
|
220940
|
+
file: `${relative$1(root, verdictsDir)}/${name}`,
|
|
220941
|
+
text: fs.read(join(verdictsDir, name)) ?? ""
|
|
220942
|
+
};
|
|
220943
|
+
}), {
|
|
220944
|
+
axes,
|
|
220945
|
+
proposals
|
|
220946
|
+
});
|
|
220947
|
+
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`);
|
|
220948
|
+
if (recalc.missing.length === 0) {
|
|
220949
|
+
const citation = Array.from({ length: judges }, (_, index) => `04-verdicts/J${index + 1}.md`).join(", ");
|
|
220950
|
+
for (const proposal of proposals) {
|
|
220951
|
+
const declared = matrix.medians[proposal];
|
|
220952
|
+
const value = recalc.medians[proposal];
|
|
220953
|
+
if (declared === void 0 || value === void 0 || declared === value) continue;
|
|
220954
|
+
add("waves.decision_median_mismatch", at, `${proposal}: mediana declarada ${declared} y recalculada ${value} desde ${citation}`);
|
|
220955
|
+
}
|
|
220956
|
+
}
|
|
220957
|
+
}
|
|
220958
|
+
if (matrix.margins.length > 0) {
|
|
220959
|
+
const dissent = normalize$1(matrix.dissent ?? "");
|
|
220960
|
+
for (const row of matrix.margins) {
|
|
220961
|
+
if (row.margin >= 0 || dissent.includes(normalize$1(row.judge))) continue;
|
|
220962
|
+
add("waves.decision_undisclosed_dissent", at, `${row.judge}: margen ${row.margin} y no aparece en "## Disidencias"`);
|
|
220963
|
+
}
|
|
220964
|
+
}
|
|
220965
|
+
}
|
|
220394
220966
|
if (!/^#{1,3}\s+\d*\.?\s*disidencias/im.test(text)) add("waves.decision_without_dissent", at, "falta la seccion \"## Disidencias\"");
|
|
220395
220967
|
if (text.length < thresholds.minDecisionBytes) add("waves.decision_thin", at, `${text.length} B < ${thresholds.minDecisionBytes} B minimos`);
|
|
220396
220968
|
const numbers = text.match(/\b\d+(?:[.,]\d+)?\b/g)?.length ?? 0;
|
|
@@ -220479,10 +221051,16 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220479
221051
|
if (tasks.length < thresholds.minTasks) add("tasks.count", null, `${tasks.length} tasks < ${thresholds.minTasks} minimas`);
|
|
220480
221052
|
});
|
|
220481
221053
|
block("ac", () => {
|
|
220482
|
-
const vague = vocabulary.vagueWords.map((word) => normalize$1(word)).filter(Boolean)
|
|
220483
|
-
|
|
221054
|
+
const vague = vocabulary.vagueWords.map((word) => normalize$1(word)).filter(Boolean).map((word) => ({
|
|
221055
|
+
word,
|
|
221056
|
+
root: word.replace(/[aeiou]$/, "")
|
|
221057
|
+
})).filter((entry) => entry.root !== "");
|
|
221058
|
+
const units = asArray$1(record$1(state.raw["vocabulary"])["units"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
221059
|
+
const falsifierLexicon = record$1(state.raw["falsifier"]);
|
|
221060
|
+
const stateVerbs = asArray$1(falsifierLexicon["stateVerbs"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
221061
|
+
const stateObjects = asArray$1(falsifierLexicon["stateObjects"]).map(str$2).map(normalize$1).filter(Boolean);
|
|
220484
221062
|
const withFalsifier = /* @__PURE__ */ new Set();
|
|
220485
|
-
const
|
|
221063
|
+
const openWaves = new Set(state.wavesOpen);
|
|
220486
221064
|
for (const task of tasks) {
|
|
220487
221065
|
const taskId = str$2(task["id"]);
|
|
220488
221066
|
for (const raw of asArray$1(task["ac"])) {
|
|
@@ -220502,31 +221080,67 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220502
221080
|
}
|
|
220503
221081
|
const metric = str$2(ac["metric"]);
|
|
220504
221082
|
if (metric !== "" && metric.length < thresholds.minMetricChars) add("ac.short_metric", at, `"metric" < ${thresholds.minMetricChars} caracteres`);
|
|
220505
|
-
const
|
|
220506
|
-
|
|
220507
|
-
|
|
220508
|
-
const
|
|
220509
|
-
if (
|
|
221083
|
+
const threshold = str$2(ac["threshold"]);
|
|
221084
|
+
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`);
|
|
221085
|
+
const prose = normalize$1(`${str$2(ac["then"])} ${threshold} ${metric}`);
|
|
221086
|
+
const vagueHit = vague.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry.root)}[a-z]{0,10}\\b`).test(prose));
|
|
221087
|
+
if (vagueHit !== void 0) {
|
|
221088
|
+
const matched = new RegExp(`\\b${escapeRegExp$1(vagueHit.root)}[a-z]{0,10}\\b`).exec(prose)?.[0] ?? vagueHit.root;
|
|
221089
|
+
add("ac.vague_language", at, `"${matched}" contiene la raiz "${vagueHit.root}" de "${vagueHit.word}": no es medible`);
|
|
221090
|
+
}
|
|
220510
221091
|
const verify = str$2(ac["verify"]).trim();
|
|
220511
221092
|
if (verify !== "") {
|
|
220512
221093
|
const command = verify.split(/\s+/)[0] ?? "";
|
|
220513
221094
|
if (!vocabulary.verifyCommands.includes(command)) add("ac.verify_not_command", at, `"${command}" no es un comando de la lista permitida`);
|
|
220514
221095
|
else {
|
|
220515
|
-
|
|
220516
|
-
|
|
220517
|
-
|
|
220518
|
-
|
|
221096
|
+
let argv;
|
|
221097
|
+
try {
|
|
221098
|
+
argv = splitCommand(verify);
|
|
221099
|
+
} catch (error) {
|
|
221100
|
+
add("ac.verify_command_unsafe", at, error instanceof Error ? error.message : String(error));
|
|
221101
|
+
}
|
|
221102
|
+
if (argv !== void 0) {
|
|
221103
|
+
let escaped;
|
|
221104
|
+
for (const token of argv) {
|
|
221105
|
+
if (token.startsWith("-") || !token.includes("/")) continue;
|
|
221106
|
+
try {
|
|
221107
|
+
containedPath(root, token);
|
|
221108
|
+
} catch {
|
|
221109
|
+
escaped = token;
|
|
221110
|
+
break;
|
|
221111
|
+
}
|
|
221112
|
+
}
|
|
221113
|
+
if (escaped !== void 0) add("ac.verify_command_unsafe", at, `el token "${escaped}" escapa de la raiz del paquete`);
|
|
221114
|
+
else {
|
|
221115
|
+
const token = argv.slice(1).find((item) => !item.startsWith("-") && item.includes("/"));
|
|
221116
|
+
if (token === void 0) add("ac.verify_outside_test_plan", at, "el comando no apunta a ningun fichero o directorio verificable");
|
|
221117
|
+
else {
|
|
221118
|
+
const target = token.replace(/^\.\//, "");
|
|
221119
|
+
if (!vocabulary.verifyPrefixes.some((prefix) => target.startsWith(prefix))) add("ac.verify_outside_test_plan", at, `"${target}" fuera del test plan declarado`);
|
|
221120
|
+
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`);
|
|
221121
|
+
const destination = join(root, target);
|
|
221122
|
+
const isTest = /(^|\/)test\//.test(target) || /\.test\./.test(target);
|
|
221123
|
+
const exempt = /(^|\/)scripts\//.test(target);
|
|
221124
|
+
if (isTest && !exempt && fs.exists(destination) && fs.isDirectory(destination) === false) {
|
|
221125
|
+
if ((fs.read(destination) ?? "").match(ASSERTION) === null) add("ac.verify_stub", at, `el destino "${target}" no tiene ninguna asercion: el verify no mide nada`);
|
|
221126
|
+
}
|
|
221127
|
+
}
|
|
221128
|
+
}
|
|
221129
|
+
}
|
|
220519
221130
|
}
|
|
220520
221131
|
}
|
|
220521
221132
|
const falsifier = record$1(ac["falsifier"]);
|
|
220522
221133
|
if (Object.keys(falsifier).length > 0) {
|
|
220523
221134
|
const mutation = str$2(falsifier["mutation"]);
|
|
220524
221135
|
const expect = str$2(falsifier["expect"]);
|
|
220525
|
-
const script = str$2(falsifier["script"]);
|
|
220526
221136
|
if (mutation.length < thresholds.minFieldChars) add("ac.falsifier_thin", at, "falsifier.mutation insuficiente");
|
|
220527
221137
|
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
221138
|
else withFalsifier.add(taskId);
|
|
221139
|
+
const normalizedMutation = normalize$1(mutation);
|
|
221140
|
+
const verb = stateVerbs.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry)}[a-z]{0,4}\\b`).test(normalizedMutation));
|
|
221141
|
+
const object = stateObjects.find((entry) => new RegExp(`\\b${escapeRegExp$1(entry)}s?\\b`).test(normalizedMutation));
|
|
221142
|
+
const reversible = str$2(falsifier["script"]).trim() !== "" || str$2(falsifier["restore"]).trim() !== "";
|
|
221143
|
+
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
221144
|
}
|
|
220531
221145
|
}
|
|
220532
221146
|
}
|
|
@@ -220588,14 +221202,17 @@ function runWaveGate(fs, root, cfg) {
|
|
|
220588
221202
|
waves: cfg.waves.length,
|
|
220589
221203
|
epics: epics.length,
|
|
220590
221204
|
tasks: tasks.length,
|
|
220591
|
-
ac: totalAc
|
|
221205
|
+
ac: totalAc,
|
|
221206
|
+
notRun: NOT_RUN_BLOCKS
|
|
220592
221207
|
}
|
|
220593
221208
|
};
|
|
220594
221209
|
}
|
|
220595
|
-
var DECISION_FILE, AC_FIELDS, normalize$1, relative$1;
|
|
221210
|
+
var DECISION_FILE, BRIEF_TEMPLATE, 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
221211
|
var init_checks = __esmMin((() => {
|
|
220597
221212
|
init_config$6();
|
|
221213
|
+
init_runner();
|
|
220598
221214
|
DECISION_FILE = "06-DECISION.md";
|
|
221215
|
+
BRIEF_TEMPLATE = "workflow/templates/brief.md";
|
|
220599
221216
|
AC_FIELDS = [
|
|
220600
221217
|
"id",
|
|
220601
221218
|
"given",
|
|
@@ -220606,8 +221223,24 @@ var init_checks = __esmMin((() => {
|
|
|
220606
221223
|
"verify",
|
|
220607
221224
|
"falsifier"
|
|
220608
221225
|
];
|
|
221226
|
+
OPERATOR_WITH_NUMBER = /[=<>≥≤]\s*\d|\b(?:mayor|menor|igual|al menos|como maximo|como minimo)\b[^0-9]{0,20}\d/;
|
|
221227
|
+
EXACT_VALUE = /\b\d+(?:[.,]\d+)?\s+(?:exacto|exacta|exactos|exactas|fijo|fija|justo|justa)\b/;
|
|
221228
|
+
ASSERTION = /\bassert\b|\bexpect\s*\(|\bit\s*\(|\btest\s*\(|\bfailures\b|process\.exit\s*\(\s*(?!0\b)/g;
|
|
221229
|
+
escapeRegExp$1 = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
221230
|
+
NOT_RUN_BLOCKS = [{
|
|
221231
|
+
block: "regression",
|
|
221232
|
+
closedBy: "oracle"
|
|
221233
|
+
}, {
|
|
221234
|
+
block: "schemas",
|
|
221235
|
+
closedBy: "oracle"
|
|
221236
|
+
}];
|
|
220609
221237
|
normalize$1 = (value) => value.normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").toLowerCase();
|
|
220610
221238
|
relative$1 = (root, path) => path.startsWith(root) ? path.slice(root.length).replaceAll("\\", "/").replace(/^\/+/, "") : path;
|
|
221239
|
+
DECISION_SEPARATOR = /^:?-{2,}:?$/;
|
|
221240
|
+
DECISION_PROPOSAL = /^p\d+$/;
|
|
221241
|
+
DECISION_LEADING_NUMBER = /^[+-]?\d+(?:[.,]\d+)?/;
|
|
221242
|
+
DECISION_JUDGE = /^J\d+$/;
|
|
221243
|
+
DECISION_SIGNED_MARGIN = /^([+-]?\d+(?:[.,]\d+)?)$/;
|
|
220611
221244
|
}));
|
|
220612
221245
|
// ../../packages/agent-core-v2/src/features/wave/tools/gate/gateRunner.ts
|
|
220613
221246
|
function runWaveGateForRoot(input) {
|
|
@@ -220629,6 +221262,7 @@ function runWaveGateForRoot(input) {
|
|
|
220629
221262
|
};
|
|
220630
221263
|
const lines = [`GATE — ${report.ok ? "verde" : "con hallazgos"}`, ""];
|
|
220631
221264
|
for (const block of report.blocks) lines.push(`${block.ok ? "OK " : "FAIL"} ${block.name}`);
|
|
221265
|
+
for (const entry of report.summary.notRun) lines.push(`NO EJECUTADO ${entry.block} — cerrado por ${entry.closedBy}`);
|
|
220632
221266
|
if (report.findings.length > 0) {
|
|
220633
221267
|
lines.push("", `PENDIENTE: ${report.findings.length} hallazgo(s)`, "");
|
|
220634
221268
|
for (const finding of report.findings) lines.push(` - ${finding.code}${finding.path === null ? "" : ` ${finding.path}`} — ${finding.message}`);
|
|
@@ -220687,168 +221321,37 @@ var init_verify$1 = __esmMin((() => {
|
|
|
220687
221321
|
init_instantiation();
|
|
220688
221322
|
WaveVerifyToolInputSchema = object$1({
|
|
220689
221323
|
task: string().min(3),
|
|
220690
|
-
root: string().optional()
|
|
221324
|
+
root: string().optional(),
|
|
221325
|
+
ac: string().min(3).optional(),
|
|
221326
|
+
dryRun: boolean$1().optional(),
|
|
221327
|
+
allowDeclared: boolean$1().optional()
|
|
220691
221328
|
}).strict();
|
|
220692
221329
|
IWaveVerifyTool = createDecorator("waveVerifyTool");
|
|
220693
221330
|
}));
|
|
220694
|
-
// ../../packages/agent-core-v2/src/features/wave/
|
|
220695
|
-
function
|
|
220696
|
-
|
|
220697
|
-
|
|
220698
|
-
|
|
220699
|
-
|
|
220700
|
-
if (quote !== void 0) {
|
|
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;
|
|
220723
|
-
}
|
|
220724
|
-
function containPaths(argv, root) {
|
|
220725
|
-
for (const token of argv) {
|
|
220726
|
-
if (token.startsWith("-")) continue;
|
|
220727
|
-
if (!token.includes("/") && !/\.(mjs|cjs|js|ts|sh)$/.test(token)) continue;
|
|
220728
|
-
containedPath(root, token);
|
|
220729
|
-
}
|
|
221331
|
+
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verifyRunner.ts
|
|
221332
|
+
function failure$1(error) {
|
|
221333
|
+
return {
|
|
221334
|
+
output: error instanceof Error ? error.message : String(error),
|
|
221335
|
+
isError: true
|
|
221336
|
+
};
|
|
220730
221337
|
}
|
|
220731
|
-
function
|
|
220732
|
-
let
|
|
221338
|
+
function runDry(root, config, input) {
|
|
221339
|
+
let selected;
|
|
220733
221340
|
try {
|
|
220734
|
-
|
|
220735
|
-
const binary = (argv[0] ?? "").replace(/\.exe$/i, "");
|
|
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);
|
|
221341
|
+
selected = selectTaskCriteria(nodeWaveFs, root, config, input.task, input.ac);
|
|
220739
221342
|
} catch (error) {
|
|
220740
|
-
return
|
|
220741
|
-
ok: false,
|
|
220742
|
-
output: `rechazado: ${error instanceof Error ? error.message : String(error)}`,
|
|
220743
|
-
rejected: true
|
|
220744
|
-
};
|
|
221343
|
+
return failure$1(error);
|
|
220745
221344
|
}
|
|
220746
|
-
const
|
|
220747
|
-
|
|
220748
|
-
|
|
220749
|
-
|
|
220750
|
-
|
|
220751
|
-
|
|
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
|
|
220758
|
-
};
|
|
220759
|
-
return {
|
|
220760
|
-
ok: result.status === 0,
|
|
220761
|
-
output,
|
|
220762
|
-
rejected: false
|
|
220763
|
-
};
|
|
220764
|
-
}
|
|
220765
|
-
function evaluateMutant(ac, verifyCommand, options) {
|
|
220766
|
-
const script = asText$1(asRecord$2(ac["falsifier"])["script"]);
|
|
220767
|
-
if (script === "") return {
|
|
220768
|
-
state: "declarado",
|
|
220769
|
-
detail: "sin falsifier.script: el AC queda declarado y cuenta como FALLO"
|
|
220770
|
-
};
|
|
220771
|
-
const apply = runCommand$2(`${script} apply`, options);
|
|
220772
|
-
if (apply.rejected) return {
|
|
220773
|
-
state: "rechazado",
|
|
220774
|
-
detail: `apply rechazado: ${apply.output}`
|
|
220775
|
-
};
|
|
220776
|
-
if (!apply.ok) return {
|
|
220777
|
-
state: "error",
|
|
220778
|
-
detail: `apply fallo: ${apply.output}`
|
|
220779
|
-
};
|
|
220780
|
-
const mutated = runCommand$2(verifyCommand, options);
|
|
220781
|
-
const restore = runCommand$2(`${script} restore`, options);
|
|
220782
|
-
const after = runCommand$2(verifyCommand, options);
|
|
220783
|
-
if (restore.rejected || !restore.ok) return {
|
|
220784
|
-
state: "error",
|
|
220785
|
-
detail: `restore fallo, el arbol puede estar sucio: ${restore.output}`
|
|
220786
|
-
};
|
|
220787
|
-
if (mutated.ok) return {
|
|
220788
|
-
state: "sobrevive",
|
|
220789
|
-
detail: "el verify pasa con la mutacion aplicada: el AC no muerde"
|
|
220790
|
-
};
|
|
220791
|
-
if (!after.ok) return {
|
|
220792
|
-
state: "error",
|
|
220793
|
-
detail: "el verify no vuelve a verde tras restaurar"
|
|
220794
|
-
};
|
|
220795
|
-
return {
|
|
220796
|
-
state: "muerto",
|
|
220797
|
-
detail: "rojo con la mutacion, verde tras restaurar"
|
|
220798
|
-
};
|
|
220799
|
-
}
|
|
220800
|
-
function verifyTask(fs, root, cfg, taskId, options) {
|
|
220801
|
-
const tasksDir = containedPath(root, cfg.layout.backlog);
|
|
220802
|
-
const file = walk$1(fs, join(tasksDir, "tasks"), (path) => path.endsWith(`${taskId}.json`))[0];
|
|
220803
|
-
if (file === void 0) throw new Error(`no encuentro la task ${taskId} en ${cfg.layout.backlog}/tasks/`);
|
|
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
|
|
220810
|
-
};
|
|
220811
|
-
const acs = [];
|
|
220812
|
-
let declared = 0;
|
|
220813
|
-
for (const raw of asArray$2(task["ac"])) {
|
|
220814
|
-
const ac = asRecord$2(raw);
|
|
220815
|
-
const verifyCommand = asText$1(ac["verify"]);
|
|
220816
|
-
const verify = runCommand$2(verifyCommand, runOptions);
|
|
220817
|
-
const mutant = evaluateMutant(ac, verifyCommand, runOptions);
|
|
220818
|
-
if (mutant.state === "declarado") declared++;
|
|
220819
|
-
const ok = verify.ok && mutant.state === "muerto";
|
|
220820
|
-
acs.push({
|
|
220821
|
-
acId: asText$1(ac["id"]),
|
|
220822
|
-
verify,
|
|
220823
|
-
mutant,
|
|
220824
|
-
ok
|
|
220825
|
-
});
|
|
221345
|
+
const lines = [`TASK ${selected.taskId} · dryRun: no se ejecuta ningun comando`, ""];
|
|
221346
|
+
for (const ac of selected.criteria) {
|
|
221347
|
+
const falsifier = asRecord$2(ac["falsifier"]);
|
|
221348
|
+
lines.push(`dry ${asText$1(ac["id"])}`);
|
|
221349
|
+
lines.push(` verify: ${asText$1(ac["verify"])}`);
|
|
221350
|
+
lines.push(` mutacion: ${asText$1(falsifier["mutation"])}`);
|
|
220826
221351
|
}
|
|
220827
|
-
|
|
220828
|
-
|
|
220829
|
-
acs,
|
|
220830
|
-
declared,
|
|
220831
|
-
ok: acs.length > 0 && acs.every((ac) => ac.ok)
|
|
220832
|
-
};
|
|
221352
|
+
lines.push("", `criterios ${selected.criteria.length} · comandos 0`);
|
|
221353
|
+
return { output: lines.join("\n") };
|
|
220833
221354
|
}
|
|
220834
|
-
var SHELL_METACHARACTERS, DEFAULT_TIMEOUT_MS$1;
|
|
220835
|
-
var init_runner = __esmMin((() => {
|
|
220836
|
-
init_config$6();
|
|
220837
|
-
init_fsJson();
|
|
220838
|
-
SHELL_METACHARACTERS = /* @__PURE__ */ new Set([
|
|
220839
|
-
"|",
|
|
220840
|
-
"&",
|
|
220841
|
-
";",
|
|
220842
|
-
"<",
|
|
220843
|
-
">",
|
|
220844
|
-
"`",
|
|
220845
|
-
"$",
|
|
220846
|
-
"\n",
|
|
220847
|
-
"\r"
|
|
220848
|
-
]);
|
|
220849
|
-
DEFAULT_TIMEOUT_MS$1 = 6e5;
|
|
220850
|
-
}));
|
|
220851
|
-
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verifyRunner.ts
|
|
220852
221355
|
function runWaveVerifyForRoot(input) {
|
|
220853
221356
|
const root = resolve(input.root);
|
|
220854
221357
|
const config = readWaveConfig(nodeWaveFs, root);
|
|
@@ -220856,7 +221359,16 @@ function runWaveVerifyForRoot(input) {
|
|
|
220856
221359
|
output: `no hay workflow.config.json en ${root}`,
|
|
220857
221360
|
isError: true
|
|
220858
221361
|
};
|
|
220859
|
-
|
|
221362
|
+
if (input.dryRun === true) return runDry(root, config, input);
|
|
221363
|
+
let result;
|
|
221364
|
+
try {
|
|
221365
|
+
result = verifyTask(nodeWaveFs, root, config, input.task, {
|
|
221366
|
+
ac: input.ac,
|
|
221367
|
+
allowDeclared: input.allowDeclared
|
|
221368
|
+
});
|
|
221369
|
+
} catch (error) {
|
|
221370
|
+
return failure$1(error);
|
|
221371
|
+
}
|
|
220860
221372
|
const lines = [`TASK ${result.taskId}`, ""];
|
|
220861
221373
|
for (const ac of result.acs) {
|
|
220862
221374
|
lines.push(`${ac.ok ? "ok " : "FAIL"} ${ac.acId} verify ${ac.verify.ok ? "verde" : "rojo"} mutante ${ac.mutant.state}`);
|
|
@@ -220872,13 +221384,14 @@ function runWaveVerifyForRoot(input) {
|
|
|
220872
221384
|
}
|
|
220873
221385
|
var init_verifyRunner = __esmMin((() => {
|
|
220874
221386
|
init_config$6();
|
|
221387
|
+
init_fsJson();
|
|
220875
221388
|
init_nodeFs();
|
|
220876
221389
|
init_runner();
|
|
220877
221390
|
}));
|
|
220878
221391
|
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verify.md?raw
|
|
220879
221392
|
var verify_default;
|
|
220880
221393
|
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";
|
|
221394
|
+
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
221395
|
}));
|
|
220883
221396
|
// ../../packages/agent-core-v2/src/features/wave/tools/verify/verifyTool.ts
|
|
220884
221397
|
var WaveVerifyTool;
|
|
@@ -220904,7 +221417,10 @@ var init_verifyTool = __esmMin((() => {
|
|
|
220904
221417
|
approvalRule: this.name,
|
|
220905
221418
|
execute: () => Promise.resolve(runWaveVerifyForRoot({
|
|
220906
221419
|
root: args.root ?? this.sessionContext.cwd,
|
|
220907
|
-
task: args.task
|
|
221420
|
+
task: args.task,
|
|
221421
|
+
ac: args.ac,
|
|
221422
|
+
dryRun: args.dryRun,
|
|
221423
|
+
allowDeclared: args.allowDeclared
|
|
220908
221424
|
}))
|
|
220909
221425
|
};
|
|
220910
221426
|
}
|
|
@@ -220995,7 +221511,7 @@ var init_flag$2 = __esmMin((() => {
|
|
|
220995
221511
|
init_wave$3();
|
|
220996
221512
|
init_waveFeature();
|
|
220997
221513
|
waveFlag = {
|
|
220998
|
-
id: WAVE_FLAG_ID
|
|
221514
|
+
id: WAVE_FLAG_ID,
|
|
220999
221515
|
title: "Wave workflow",
|
|
221000
221516
|
description: "Enable the wave workflow: adversarial design rounds with isolated seats, the package gate, and task verification tools.",
|
|
221001
221517
|
env: WAVE_FLAG_ENV,
|
|
@@ -394734,10 +395250,6 @@ function swarmArgumentCompletions(argumentPrefix) {
|
|
|
394734
395250
|
function towerArgumentCompletions(argumentPrefix) {
|
|
394735
395251
|
return completeLeadingArg(TOWER_ARG_COMPLETIONS, argumentPrefix);
|
|
394736
395252
|
}
|
|
394737
|
-
/** Argument autocompletion for the `/wave` command (subcommands). */
|
|
394738
|
-
function waveArgumentCompletions(argumentPrefix) {
|
|
394739
|
-
return completeLeadingArg(WAVE_ARG_COMPLETIONS, argumentPrefix);
|
|
394740
|
-
}
|
|
394741
395253
|
/** Argument autocompletion for the `/add-dir` command. */
|
|
394742
395254
|
function addDirArgumentCompletions(argumentPrefix) {
|
|
394743
395255
|
if (isPathLikeAddDirArgument(argumentPrefix)) return completeAddDirPath(argumentPrefix);
|
|
@@ -394817,7 +395329,7 @@ function resolveSlashCommandAvailability(command, args) {
|
|
|
394817
395329
|
function sortSlashCommands(commands) {
|
|
394818
395330
|
return [...commands].toSorted((a, b) => (b.priority ?? 0) - (a.priority ?? 0) || a.name.localeCompare(b.name));
|
|
394819
395331
|
}
|
|
394820
|
-
var GOAL_ARG_COMPLETIONS, GOAL_NEXT_ARG_COMPLETIONS, SWARM_ARG_COMPLETIONS, TOWER_ARG_COMPLETIONS,
|
|
395332
|
+
var GOAL_ARG_COMPLETIONS, GOAL_NEXT_ARG_COMPLETIONS, SWARM_ARG_COMPLETIONS, TOWER_ARG_COMPLETIONS, ADD_DIR_ARG_COMPLETIONS, BUILTIN_SLASH_COMMANDS;
|
|
394821
395333
|
var init_registry$2 = __esmMin((() => {
|
|
394822
395334
|
init_dist$5();
|
|
394823
395335
|
init_complete_args();
|
|
@@ -394876,20 +395388,6 @@ var init_registry$2 = __esmMin((() => {
|
|
|
394876
395388
|
description: "Turn tower mode off"
|
|
394877
395389
|
}
|
|
394878
395390
|
];
|
|
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
395391
|
ADD_DIR_ARG_COMPLETIONS = [{
|
|
394894
395392
|
value: "list",
|
|
394895
395393
|
description: "Show configured additional workspace directories"
|
|
@@ -394954,8 +395452,7 @@ var init_registry$2 = __esmMin((() => {
|
|
|
394954
395452
|
aliases: [],
|
|
394955
395453
|
description: "Run a design wave: brief, adversarial swarm, gate and execution",
|
|
394956
395454
|
priority: 90,
|
|
394957
|
-
argumentHint: "
|
|
394958
|
-
completeArgs: waveArgumentCompletions,
|
|
395455
|
+
argumentHint: "<objetivo de la oleada>",
|
|
394959
395456
|
availability: "idle-only",
|
|
394960
395457
|
experimentalFlag: "wave"
|
|
394961
395458
|
},
|
|
@@ -477583,74 +478080,24 @@ function buildWavePrompt(args) {
|
|
|
477583
478080
|
"",
|
|
477584
478081
|
"Reglas de la oleada:",
|
|
477585
478082
|
"- Usa las tools Wave: `WaveOpen` para abrirla, `WaveRound` para obtener el prompt de cada asiento, `WaveSubmit` para que cada asiento entregue su artefacto, `WaveDecide` para el quórum, `WaveGate` para el paquete y `WaveVerify` para cerrar tasks.",
|
|
477586
|
-
"- Lanza un agente por asiento con `Agent` (o `AgentSwarm` si el usuario activó swarm)
|
|
477587
|
-
"-
|
|
478083
|
+
"- Lanza un agente por asiento con `Agent` (o `AgentSwarm` si el usuario activó swarm) pasando `subagent_type: \"wave-seat\"` y el prompt que devuelve `WaveRound`. No inventes el prompt ni cambies el rol.",
|
|
478084
|
+
"- El asiento es de solo lectura: `Read`, `Glob`, `Grep` y `WaveSubmit`. Nunca escribe con Write/Edit: entrega con `WaveSubmit`, que ata rol y ruta.",
|
|
477588
478085
|
"- Si el brief no tiene las siete secciones, para y pide que se rellenen; no lo escribas tú.",
|
|
477589
478086
|
"- Sin `adopt` de `WaveDecide`, lanza `refine` y después `audit`; con dos rondas sin quórum, adopta R1 con disidencia escrita.",
|
|
477590
478087
|
"- La oleada no está cerrada hasta que `WaveGate` sale en verde. Si sale en rojo, dilo con los códigos de hallazgo."
|
|
477591
478088
|
].join("\n");
|
|
477592
478089
|
}
|
|
477593
478090
|
async function handleWaveCommand(host, args) {
|
|
477594
|
-
const
|
|
477595
|
-
|
|
477596
|
-
if (sub === "on" || sub === "off") {
|
|
477597
|
-
await setWaveExperiment(host, sub === "on");
|
|
477598
|
-
return;
|
|
477599
|
-
}
|
|
477600
|
-
if (sub === "" || sub === "status") {
|
|
477601
|
-
await reportWaveStatus(host, sub === "");
|
|
477602
|
-
return;
|
|
477603
|
-
}
|
|
477604
|
-
if (sub === "help") {
|
|
478091
|
+
const objective = args.trim();
|
|
478092
|
+
if (objective === "") {
|
|
477605
478093
|
host.showNotice("Wave", WAVE_USAGE);
|
|
477606
478094
|
return;
|
|
477607
478095
|
}
|
|
477608
|
-
host.sendNormalUserInput(buildWavePrompt(
|
|
478096
|
+
host.sendNormalUserInput(buildWavePrompt(objective));
|
|
477609
478097
|
}
|
|
477610
|
-
|
|
477611
|
-
let enabled;
|
|
477612
|
-
try {
|
|
477613
|
-
enabled = (await host.harness.getExperimentalFeatures()).find((feature) => feature.id === WAVE_FLAG_ID)?.enabled === true;
|
|
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;
|
|
477640
|
-
}
|
|
477641
|
-
try {
|
|
477642
|
-
const reloadedSession = await host.harness.reloadSession({ id: host.session.id });
|
|
477643
|
-
await host.reloadCurrentSessionView(reloadedSession, "Wave experiment on. Session reloaded — `/wave <objetivo>` is ready.");
|
|
477644
|
-
} catch (error) {
|
|
477645
|
-
host.showError(`Wave experiment is on, but the session could not be reloaded: ${formatErrorMessage$2(error)}`);
|
|
477646
|
-
}
|
|
477647
|
-
}
|
|
477648
|
-
var WAVE_USAGE, WAVE_FLAG_ID;
|
|
478098
|
+
var WAVE_USAGE;
|
|
477649
478099
|
var init_wave = __esmMin((() => {
|
|
477650
|
-
|
|
477651
|
-
init_experimental_flags();
|
|
477652
|
-
WAVE_USAGE = "Uso: /wave <objetivo de la oleada> — abre una oleada de diseño, lanza el swarm adversarial y cierra con el gate. Los subcomandos `/wave on`, `/wave off` y `/wave status` activan o consultan el experimento.";
|
|
477653
|
-
WAVE_FLAG_ID = "wave";
|
|
478100
|
+
WAVE_USAGE = "Uso: /wave <objetivo de la oleada> — abre una oleada de diseño, lanza el swarm adversarial y cierra con el gate. Requiere NEXGEN_EXPERIMENTAL_WAVE.";
|
|
477654
478101
|
}));
|
|
477655
478102
|
// src/tui/commands/tower.ts
|
|
477656
478103
|
async function handleTowerCommand(host, args) {
|
|
@@ -484747,7 +485194,6 @@ var init_commands = __esmMin((() => {
|
|
|
484747
485194
|
init_config();
|
|
484748
485195
|
init_swarm();
|
|
484749
485196
|
init_tower();
|
|
484750
|
-
init_wave();
|
|
484751
485197
|
init_info();
|
|
484752
485198
|
init_plugins();
|
|
484753
485199
|
init_reload();
|