vibeostheog 0.24.14 → 0.24.15
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/CHANGELOG.md +21 -3
- package/dist/vibeOS.js +270 -137
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
|
+
## 0.24.15
|
|
2
|
+
- feat: smooth delegation UX — conversational reasoning over error injection
|
|
3
|
+
- fix: preserve local agent mode in remote control merge
|
|
4
|
+
- fix: harden live regression paths (#140)
|
|
5
|
+
- fix: write npm auth for github release publish
|
|
6
|
+
- fix: reset api fallback on token refresh (#138)
|
|
7
|
+
- fix: _prevBlackboxState -> _latestBlackboxState, update pattern key test
|
|
8
|
+
- fix: sync-ts-build was cleaning JS artifacts without copying compiled output back
|
|
9
|
+
- fix: forensic anti-lying + quality enforcement pipeline
|
|
10
|
+
- docs: add cross-project index, DEV ONLY markers, ESLint cleanup
|
|
11
|
+
- test: add 13 cascade integration tests for forensic quality pipeline
|
|
12
|
+
- chore: v0.24.14
|
|
13
|
+
- chore: sync package version to v0.24.12
|
|
14
|
+
- chore: sync package version to latest github release
|
|
15
|
+
- chore: sync package version to latest release
|
|
16
|
+
Fix live regressions and add integration coverage (#139)
|
|
17
|
+
Merge pull request #136 from DrunkkToys/release/v0.24.8-merge
|
|
18
|
+
|
|
19
|
+
|
|
1
20
|
## 0.24.14
|
|
2
21
|
- feat: smooth delegation UX — conversational reasoning over error injection
|
|
3
|
-
- fix: preserve
|
|
4
|
-
- fix: harden live regression paths
|
|
22
|
+
- fix: preserve local agent mode in remote control merge
|
|
23
|
+
- fix: harden live regression paths (#140)
|
|
5
24
|
- fix: write npm auth for github release publish
|
|
6
25
|
- fix: reset api fallback on token refresh (#138)
|
|
7
26
|
- fix: _prevBlackboxState -> _latestBlackboxState, update pattern key test
|
|
@@ -9,7 +28,6 @@
|
|
|
9
28
|
- fix: forensic anti-lying + quality enforcement pipeline
|
|
10
29
|
- docs: add cross-project index, DEV ONLY markers, ESLint cleanup
|
|
11
30
|
- test: add 13 cascade integration tests for forensic quality pipeline
|
|
12
|
-
- chore: sync package version to v0.24.13
|
|
13
31
|
- chore: sync package version to v0.24.12
|
|
14
32
|
- chore: sync package version to latest github release
|
|
15
33
|
- chore: sync package version to latest release
|
package/dist/vibeOS.js
CHANGED
|
@@ -2534,42 +2534,56 @@ function writeSessionOptMode(sid, mode) {
|
|
|
2534
2534
|
}
|
|
2535
2535
|
}
|
|
2536
2536
|
|
|
2537
|
-
// src/lib/pattern-helpers.
|
|
2537
|
+
// src/lib/pattern-helpers.js
|
|
2538
2538
|
import { relative, basename as basename2 } from "node:path";
|
|
2539
2539
|
function normalizeObservedPath(filePath, directory3) {
|
|
2540
|
-
if (!filePath || typeof filePath !== "string")
|
|
2540
|
+
if (!filePath || typeof filePath !== "string")
|
|
2541
|
+
return "unknown";
|
|
2541
2542
|
let p = filePath;
|
|
2542
2543
|
try {
|
|
2543
2544
|
if (directory3 && p.startsWith("/")) {
|
|
2544
2545
|
const rel = relative(directory3, p);
|
|
2545
|
-
if (rel && !rel.startsWith("..") && !rel.startsWith("/"))
|
|
2546
|
+
if (rel && !rel.startsWith("..") && !rel.startsWith("/"))
|
|
2547
|
+
p = rel;
|
|
2546
2548
|
}
|
|
2547
2549
|
} catch {
|
|
2548
2550
|
}
|
|
2549
2551
|
p = p.replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
2550
|
-
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p))
|
|
2552
|
+
if (/^(src\/index\.js|package\.json|README\.md|CHANGELOG\.md|tsconfig\.json)$/i.test(p))
|
|
2553
|
+
return p;
|
|
2551
2554
|
const m = p.match(/\.([a-z0-9]+)$/i);
|
|
2552
|
-
if (p.startsWith("src/") && m)
|
|
2553
|
-
|
|
2555
|
+
if (p.startsWith("src/") && m)
|
|
2556
|
+
return `src/*.${m[1].toLowerCase()}`;
|
|
2557
|
+
if (p.startsWith("tests/") && m)
|
|
2558
|
+
return `tests/*.${m[1].toLowerCase()}`;
|
|
2554
2559
|
return basename2(p) || "unknown";
|
|
2555
2560
|
}
|
|
2556
2561
|
function commandFamily(command) {
|
|
2557
2562
|
const c = String(command || "").trim().toLowerCase();
|
|
2558
|
-
if (!c)
|
|
2559
|
-
|
|
2560
|
-
if (/\
|
|
2561
|
-
|
|
2562
|
-
if (/\bnpm\s+run\s+
|
|
2563
|
-
|
|
2564
|
-
if (/\
|
|
2563
|
+
if (!c)
|
|
2564
|
+
return "unknown";
|
|
2565
|
+
if (/\bnode\s+--check\b/.test(c))
|
|
2566
|
+
return "syntax-check";
|
|
2567
|
+
if (/\bnpm\s+run\s+typecheck\b|\btsc\b.*--noemit/.test(c))
|
|
2568
|
+
return "typecheck";
|
|
2569
|
+
if (/\bnpm\s+test\b|\bnode\s+--test\b|\bvitest\b|\bjest\b|\bpytest\b/.test(c))
|
|
2570
|
+
return "test";
|
|
2571
|
+
if (/\bnpm\s+run\s+build\b|\btsc\s+-p\b/.test(c))
|
|
2572
|
+
return "build";
|
|
2573
|
+
if (/\bgit\s+status\b/.test(c))
|
|
2574
|
+
return "git-status";
|
|
2575
|
+
if (/\bgit\s+commit\b/.test(c))
|
|
2576
|
+
return "git-commit";
|
|
2565
2577
|
const first = c.replace(/^[a-z_][a-z0-9_]*=\S+\s+/g, "").split(/\s+/)[0];
|
|
2566
2578
|
return /^[a-z0-9._/-]{1,30}$/.test(first) ? first : "command";
|
|
2567
2579
|
}
|
|
2568
2580
|
function commandFailed(output) {
|
|
2569
2581
|
const code = output?.exitCode ?? output?.statusCode ?? output?.code;
|
|
2570
|
-
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
2582
|
+
if (Number.isFinite(Number(code)) && Number(code) !== 0)
|
|
2583
|
+
return true;
|
|
2571
2584
|
const raw = output?.result ?? output?.text ?? output?.content ?? output?.data ?? "";
|
|
2572
|
-
if (typeof raw !== "string")
|
|
2585
|
+
if (typeof raw !== "string")
|
|
2586
|
+
return false;
|
|
2573
2587
|
return /\b(exit code|exited with code)\s*[:=]?\s*[1-9]\b|\b(assertionerror|syntaxerror|typeerror|referenceerror)\b|\b(failed|error:|err!)\b/i.test(raw);
|
|
2574
2588
|
}
|
|
2575
2589
|
function mergeProjectBucket(dst, src) {
|
|
@@ -2586,7 +2600,8 @@ function mergeProjectBucket(dst, src) {
|
|
|
2586
2600
|
row.sessions = [.../* @__PURE__ */ new Set([...row.sessions || [], ...v?.sessions || []])].slice(-10);
|
|
2587
2601
|
row.lastSeen = [row.lastSeen, v?.lastSeen].filter(Boolean).sort().slice(-1)[0] || null;
|
|
2588
2602
|
row.summary = row.summary || v?.summary || "";
|
|
2589
|
-
if (v?.kind)
|
|
2603
|
+
if (v?.kind)
|
|
2604
|
+
row.kind = v.kind;
|
|
2590
2605
|
out[key] = row;
|
|
2591
2606
|
}
|
|
2592
2607
|
}
|
|
@@ -2605,9 +2620,11 @@ function mergeProjectBucket(dst, src) {
|
|
|
2605
2620
|
};
|
|
2606
2621
|
}
|
|
2607
2622
|
function _pruneOldSessions(state) {
|
|
2608
|
-
if (!state?.sessions)
|
|
2623
|
+
if (!state?.sessions)
|
|
2624
|
+
return;
|
|
2609
2625
|
const entries = Object.entries(state.sessions);
|
|
2610
|
-
if (entries.length <= 30)
|
|
2626
|
+
if (entries.length <= 30)
|
|
2627
|
+
return;
|
|
2611
2628
|
entries.sort((a, b) => {
|
|
2612
2629
|
const da = a[1]?.started || a[1]?.last_costed || "";
|
|
2613
2630
|
const db = b[1]?.started || b[1]?.last_costed || "";
|
|
@@ -9684,7 +9701,7 @@ function recordBudgetFirstOutcome(input = {}) {
|
|
|
9684
9701
|
import { join as join13 } from "node:path";
|
|
9685
9702
|
import { writeFileSync as writeFileSync11 } from "node:fs";
|
|
9686
9703
|
|
|
9687
|
-
// src/lib/text-compress.
|
|
9704
|
+
// src/lib/text-compress.js
|
|
9688
9705
|
var VERBOSE_LINE_RE = [
|
|
9689
9706
|
/^[\s#*/\\\-_=+|~:;'"`@\$%^&<>{}\[\]()!?.,0-9]+$/,
|
|
9690
9707
|
/^(Filed|Created|Modified|Deleted|Updated|Renamed|Copied|Moved|Changed):/,
|
|
@@ -9701,12 +9718,15 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9701
9718
|
const keyLines = [];
|
|
9702
9719
|
const otherLines = [];
|
|
9703
9720
|
for (const line of lines) {
|
|
9704
|
-
if (BULLET_PATTERNS.some((re) => re.test(line)))
|
|
9705
|
-
|
|
9721
|
+
if (BULLET_PATTERNS.some((re) => re.test(line)))
|
|
9722
|
+
keyLines.push(line);
|
|
9723
|
+
else
|
|
9724
|
+
otherLines.push(line);
|
|
9706
9725
|
}
|
|
9707
9726
|
const selected = [...keyLines];
|
|
9708
9727
|
for (const line of otherLines) {
|
|
9709
|
-
if (selected.length >= minLines && selected.join("\n").length >= targetChars)
|
|
9728
|
+
if (selected.length >= minLines && selected.join("\n").length >= targetChars)
|
|
9729
|
+
break;
|
|
9710
9730
|
selected.push(line);
|
|
9711
9731
|
}
|
|
9712
9732
|
while (selected.length > minLines && selected.join("\n").length > targetChars * 2) {
|
|
@@ -9715,7 +9735,8 @@ function extractBulletLines(lines, targetChars, minLines) {
|
|
|
9715
9735
|
return selected;
|
|
9716
9736
|
}
|
|
9717
9737
|
function compressText(text) {
|
|
9718
|
-
if (!text || typeof text !== "string")
|
|
9738
|
+
if (!text || typeof text !== "string")
|
|
9739
|
+
return text;
|
|
9719
9740
|
let lines = text.split("\n");
|
|
9720
9741
|
let removed = 0;
|
|
9721
9742
|
const out = [];
|
|
@@ -9728,14 +9749,16 @@ function compressText(text) {
|
|
|
9728
9749
|
break;
|
|
9729
9750
|
}
|
|
9730
9751
|
}
|
|
9731
|
-
if (!skip)
|
|
9752
|
+
if (!skip)
|
|
9753
|
+
out.push(line);
|
|
9732
9754
|
}
|
|
9733
9755
|
const collapsed = [];
|
|
9734
9756
|
let blanks = 0;
|
|
9735
9757
|
for (const line of out) {
|
|
9736
9758
|
if (line.trim() === "") {
|
|
9737
9759
|
blanks++;
|
|
9738
|
-
if (blanks <= 2)
|
|
9760
|
+
if (blanks <= 2)
|
|
9761
|
+
collapsed.push(line);
|
|
9739
9762
|
} else {
|
|
9740
9763
|
blanks = 0;
|
|
9741
9764
|
collapsed.push(line);
|
|
@@ -9743,10 +9766,7 @@ function compressText(text) {
|
|
|
9743
9766
|
}
|
|
9744
9767
|
let result = collapsed.join("\n").trim();
|
|
9745
9768
|
if (result.length > COMPRESS_THRESHOLD) {
|
|
9746
|
-
const targetChars = Math.max(
|
|
9747
|
-
Math.round(result.length * COMPRESS_RATIO),
|
|
9748
|
-
COMPRESS_THRESHOLD
|
|
9749
|
-
);
|
|
9769
|
+
const targetChars = Math.max(Math.round(result.length * COMPRESS_RATIO), COMPRESS_THRESHOLD);
|
|
9750
9770
|
const minLines = Math.max(1, Math.round(collapsed.length * MIN_KEPT_LINES_RATIO));
|
|
9751
9771
|
const bulletLines = extractBulletLines(collapsed, targetChars, minLines);
|
|
9752
9772
|
result = bulletLines.join("\n").trim();
|
|
@@ -10061,7 +10081,7 @@ function recordSaving(tool2, reason, saveEst, meta = {}) {
|
|
|
10061
10081
|
}
|
|
10062
10082
|
}
|
|
10063
10083
|
|
|
10064
|
-
// src/lib/constants.
|
|
10084
|
+
// src/lib/constants.js
|
|
10065
10085
|
var SAVE_EST = {
|
|
10066
10086
|
// Realistic: v4-pro (0.00057) - v4-flash (0.000182) = 0.000388/turn
|
|
10067
10087
|
WRITE_EDIT: 4e-4,
|
|
@@ -10079,7 +10099,7 @@ var COMPRESS_MARKER = "[ctx-compressed-v1]";
|
|
|
10079
10099
|
var PROTOCOL_MARKER = "[wbp-v1]";
|
|
10080
10100
|
var PROTOCOL_TEXT = PROTOCOL_MARKER + " [Worker-to-Brain Report Protocol] When synthesizing the preceding Task output: 1) EXTRACT core findings/data. 2) REFORMAT into bullet points. 3) VERIFY against the original ask. 4) SYNTHESIZE into final response.";
|
|
10081
10101
|
|
|
10082
|
-
// src/lib/templates.
|
|
10102
|
+
// src/lib/templates.js
|
|
10083
10103
|
var TEMPLATES = {
|
|
10084
10104
|
save: {
|
|
10085
10105
|
tier_bias: "cheap",
|
|
@@ -10129,7 +10149,8 @@ var TEMPLATES = {
|
|
|
10129
10149
|
var DEFAULT_TEMPLATE = "save";
|
|
10130
10150
|
var SEC_KEYWORDS = /\b(security|vuln|exploit|injection|xss|csrf|secret|credential|token leak|auth bypass|privacy|breach|backdoor|sql injection|cve)\b/i;
|
|
10131
10151
|
function detectSecuritySignal(text) {
|
|
10132
|
-
if (!text || typeof text !== "string")
|
|
10152
|
+
if (!text || typeof text !== "string")
|
|
10153
|
+
return false;
|
|
10133
10154
|
return SEC_KEYWORDS.test(text);
|
|
10134
10155
|
}
|
|
10135
10156
|
function detectBudgetSignal(creditPercent) {
|
|
@@ -10142,20 +10163,25 @@ function detectStressSpike(stressScore) {
|
|
|
10142
10163
|
return delta > 0.3 && stressScore > 0.5;
|
|
10143
10164
|
}
|
|
10144
10165
|
function resolveTemplate(prevTemplate, stressScore, userText, creditPercent, subRegime) {
|
|
10145
|
-
if (detectSecuritySignal(userText))
|
|
10166
|
+
if (detectSecuritySignal(userText))
|
|
10167
|
+
return "security";
|
|
10146
10168
|
if (detectBudgetSignal(creditPercent)) {
|
|
10147
10169
|
const regime = String(subRegime || "").toUpperCase();
|
|
10148
|
-
if (regime === "LOOPING" || regime === "DIVERGENT")
|
|
10170
|
+
if (regime === "LOOPING" || regime === "DIVERGENT")
|
|
10171
|
+
return "speed";
|
|
10149
10172
|
return "save";
|
|
10150
10173
|
}
|
|
10151
|
-
if (detectStressSpike(stressScore))
|
|
10174
|
+
if (detectStressSpike(stressScore))
|
|
10175
|
+
return "quality";
|
|
10152
10176
|
return prevTemplate || DEFAULT_TEMPLATE;
|
|
10153
10177
|
}
|
|
10154
10178
|
var _turnCount = 0;
|
|
10155
10179
|
function shouldInjectTemplate(template, prevTemplate) {
|
|
10156
10180
|
_turnCount++;
|
|
10157
|
-
if (template !== prevTemplate)
|
|
10158
|
-
|
|
10181
|
+
if (template !== prevTemplate)
|
|
10182
|
+
return true;
|
|
10183
|
+
if (_turnCount % 10 === 0)
|
|
10184
|
+
return true;
|
|
10159
10185
|
return false;
|
|
10160
10186
|
}
|
|
10161
10187
|
|
|
@@ -10164,6 +10190,18 @@ var BYTES_PER_TOKEN = 4;
|
|
|
10164
10190
|
function getVibeOSHome9() {
|
|
10165
10191
|
return process.env.VIBEOS_HOME || join14(process.env.HOME || "", ".claude");
|
|
10166
10192
|
}
|
|
10193
|
+
function mergeRemoteControlVector(remoteControlVector, localControlVector) {
|
|
10194
|
+
return {
|
|
10195
|
+
...remoteControlVector,
|
|
10196
|
+
agent_mode: localControlVector?.agent_mode,
|
|
10197
|
+
tier_bias: localControlVector?.tier_bias,
|
|
10198
|
+
optimization_mode: localControlVector?.optimization_mode,
|
|
10199
|
+
enforcement_mode: localControlVector?.enforcement_mode,
|
|
10200
|
+
flow_mode: localControlVector?.flow_mode,
|
|
10201
|
+
tdd_mode: localControlVector?.tdd_mode,
|
|
10202
|
+
thinking_mode: localControlVector?.thinking_mode
|
|
10203
|
+
};
|
|
10204
|
+
}
|
|
10167
10205
|
function resolveRestorableOpenCodeAgent(currentSel) {
|
|
10168
10206
|
const remembered = typeof currentSel?.previous_default_agent === "string" ? currentSel.previous_default_agent.trim() : "";
|
|
10169
10207
|
if (remembered && remembered !== "plan")
|
|
@@ -10216,7 +10254,7 @@ async function apiComputeControlVector(state, action, optimizationMode) {
|
|
|
10216
10254
|
const res = await remoteCall("blackboxControlVector", [state, action, optimizationMode], null);
|
|
10217
10255
|
if (res?.control_vector) {
|
|
10218
10256
|
const local = computeControlVector2(state, action, optimizationMode);
|
|
10219
|
-
return
|
|
10257
|
+
return mergeRemoteControlVector(res.control_vector, local);
|
|
10220
10258
|
}
|
|
10221
10259
|
} catch {
|
|
10222
10260
|
}
|
|
@@ -11351,7 +11389,7 @@ import { writeFileSync as writeFileSync14, appendFileSync as appendFileSync8, ex
|
|
|
11351
11389
|
import { join as join17, dirname as dirname12, basename as basename7 } from "node:path";
|
|
11352
11390
|
import { createHash as createHash5 } from "node:crypto";
|
|
11353
11391
|
|
|
11354
|
-
// src/lib/cost-anomaly.
|
|
11392
|
+
// src/lib/cost-anomaly.js
|
|
11355
11393
|
var COST_WINDOW_SIZE = 20;
|
|
11356
11394
|
var COST_ANOMALY_THRESHOLD = 3;
|
|
11357
11395
|
var COST_WARMUP_SAMPLES = 5;
|
|
@@ -11362,21 +11400,26 @@ var CostAnomalyDetector = class {
|
|
|
11362
11400
|
currentAnomalyCost = 0;
|
|
11363
11401
|
currentAnomalyMean = 0;
|
|
11364
11402
|
record(cost) {
|
|
11365
|
-
if (this.disabled)
|
|
11403
|
+
if (this.disabled)
|
|
11404
|
+
return;
|
|
11366
11405
|
this.costHistory.push(cost);
|
|
11367
11406
|
if (this.costHistory.length > COST_WINDOW_SIZE) {
|
|
11368
11407
|
this.costHistory.shift();
|
|
11369
11408
|
}
|
|
11370
11409
|
}
|
|
11371
11410
|
get mean() {
|
|
11372
|
-
if (this.costHistory.length === 0)
|
|
11411
|
+
if (this.costHistory.length === 0)
|
|
11412
|
+
return 0;
|
|
11373
11413
|
return this.costHistory.reduce((a, b) => a + b, 0) / this.costHistory.length;
|
|
11374
11414
|
}
|
|
11375
11415
|
checkAnomaly(model, cost) {
|
|
11376
|
-
if (this.disabled)
|
|
11377
|
-
|
|
11416
|
+
if (this.disabled)
|
|
11417
|
+
return false;
|
|
11418
|
+
if (this.costHistory.length < COST_WARMUP_SAMPLES)
|
|
11419
|
+
return false;
|
|
11378
11420
|
const avg = this.mean;
|
|
11379
|
-
if (avg <= 0 || cost <= avg)
|
|
11421
|
+
if (avg <= 0 || cost <= avg)
|
|
11422
|
+
return false;
|
|
11380
11423
|
const ratio = cost / avg;
|
|
11381
11424
|
if (ratio > COST_ANOMALY_THRESHOLD) {
|
|
11382
11425
|
this.currentAnomalyModel = model;
|
|
@@ -11398,7 +11441,8 @@ var CostAnomalyDetector = class {
|
|
|
11398
11441
|
};
|
|
11399
11442
|
var _costDetector = null;
|
|
11400
11443
|
function getCostAnomalyDetector() {
|
|
11401
|
-
if (!_costDetector)
|
|
11444
|
+
if (!_costDetector)
|
|
11445
|
+
_costDetector = new CostAnomalyDetector();
|
|
11402
11446
|
return _costDetector;
|
|
11403
11447
|
}
|
|
11404
11448
|
|
|
@@ -11410,9 +11454,10 @@ import { readFileSync as readFileSync15, writeFileSync as writeFileSync13, appen
|
|
|
11410
11454
|
import { join as join16, dirname as dirname11 } from "node:path";
|
|
11411
11455
|
import { createHash as createHash4 } from "node:crypto";
|
|
11412
11456
|
|
|
11413
|
-
// src/utils/tdd-helpers.
|
|
11457
|
+
// src/utils/tdd-helpers.js
|
|
11414
11458
|
function extractExports(sourceContent, ext) {
|
|
11415
|
-
if (!sourceContent || typeof sourceContent !== "string")
|
|
11459
|
+
if (!sourceContent || typeof sourceContent !== "string")
|
|
11460
|
+
return [];
|
|
11416
11461
|
const exports = [];
|
|
11417
11462
|
const seen = /* @__PURE__ */ new Set();
|
|
11418
11463
|
const add = (name, type = "function") => {
|
|
@@ -11423,51 +11468,69 @@ function extractExports(sourceContent, ext) {
|
|
|
11423
11468
|
};
|
|
11424
11469
|
switch (ext) {
|
|
11425
11470
|
case "py": {
|
|
11426
|
-
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm))
|
|
11427
|
-
|
|
11471
|
+
for (const m of sourceContent.matchAll(/^def\s+([a-zA-Z]\w*)\s*\(/gm))
|
|
11472
|
+
add(m[1]);
|
|
11473
|
+
for (const m of sourceContent.matchAll(/^class\s+([a-zA-Z_]\w*)\s*[\(:]/gm))
|
|
11474
|
+
add(m[1], "class");
|
|
11428
11475
|
break;
|
|
11429
11476
|
}
|
|
11430
11477
|
case "js":
|
|
11431
11478
|
case "mjs":
|
|
11432
11479
|
case "jsx": {
|
|
11433
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11434
|
-
|
|
11480
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11481
|
+
add(m[1]);
|
|
11482
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*=/g))
|
|
11483
|
+
add(m[1]);
|
|
11435
11484
|
if (exports.length === 0) {
|
|
11436
|
-
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm))
|
|
11485
|
+
for (const m of sourceContent.matchAll(/^(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/gm))
|
|
11486
|
+
add(m[1]);
|
|
11437
11487
|
}
|
|
11438
11488
|
break;
|
|
11439
11489
|
}
|
|
11440
11490
|
case "ts":
|
|
11441
11491
|
case "tsx": {
|
|
11442
|
-
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11443
|
-
|
|
11444
|
-
for (const m of sourceContent.matchAll(/export\s+
|
|
11492
|
+
for (const m of sourceContent.matchAll(/export\s+(?:async\s+)?function\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11493
|
+
add(m[1]);
|
|
11494
|
+
for (const m of sourceContent.matchAll(/export\s+const\s+([a-zA-Z_$]\w*)\s*[:=]/g))
|
|
11495
|
+
add(m[1]);
|
|
11496
|
+
for (const m of sourceContent.matchAll(/export\s+class\s+([a-zA-Z_$]\w*)/g))
|
|
11497
|
+
add(m[1], "class");
|
|
11445
11498
|
break;
|
|
11446
11499
|
}
|
|
11447
11500
|
case "go": {
|
|
11448
|
-
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g))
|
|
11501
|
+
for (const m of sourceContent.matchAll(/func\s+(?:\([^)]+\)\s+)?([A-Z]\w*)\s*\(/g))
|
|
11502
|
+
add(m[1]);
|
|
11449
11503
|
break;
|
|
11450
11504
|
}
|
|
11451
11505
|
case "rs": {
|
|
11452
|
-
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g))
|
|
11453
|
-
|
|
11454
|
-
for (const m of sourceContent.matchAll(/pub\s+
|
|
11506
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*</g))
|
|
11507
|
+
add(m[1]);
|
|
11508
|
+
for (const m of sourceContent.matchAll(/pub\s+fn\s+([a-zA-Z_]\w*)\s*\(/g))
|
|
11509
|
+
add(m[1]);
|
|
11510
|
+
for (const m of sourceContent.matchAll(/pub\s+struct\s+([a-zA-Z_]\w*)/g))
|
|
11511
|
+
add(m[1], "struct");
|
|
11455
11512
|
break;
|
|
11456
11513
|
}
|
|
11457
11514
|
case "rb": {
|
|
11458
|
-
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g))
|
|
11459
|
-
|
|
11515
|
+
for (const m of sourceContent.matchAll(/def\s+(?:self\.)?([a-zA-Z_]\w*[?!=]?)/g))
|
|
11516
|
+
add(m[1]);
|
|
11517
|
+
for (const m of sourceContent.matchAll(/class\s+([A-Z]\w*)/g))
|
|
11518
|
+
add(m[1], "class");
|
|
11460
11519
|
break;
|
|
11461
11520
|
}
|
|
11462
11521
|
case "java":
|
|
11463
11522
|
case "kt": {
|
|
11464
|
-
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11465
|
-
|
|
11523
|
+
for (const m of sourceContent.matchAll(/(?:public|protected)\s+(?:static\s+)?(?:final\s+)?\S+\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11524
|
+
add(m[1]);
|
|
11525
|
+
for (const m of sourceContent.matchAll(/fun\s+([a-zA-Z_$]\w*)\s*\(/g))
|
|
11526
|
+
add(m[1]);
|
|
11466
11527
|
break;
|
|
11467
11528
|
}
|
|
11468
11529
|
case "sh": {
|
|
11469
|
-
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm))
|
|
11470
|
-
|
|
11530
|
+
for (const m of sourceContent.matchAll(/^(?:function\s+)?([a-zA-Z_]\w*)\s*\(\)\s*\{/gm))
|
|
11531
|
+
add(m[1]);
|
|
11532
|
+
for (const m of sourceContent.matchAll(/^function\s+([a-zA-Z_]\w*)/gm))
|
|
11533
|
+
add(m[1]);
|
|
11471
11534
|
break;
|
|
11472
11535
|
}
|
|
11473
11536
|
}
|
|
@@ -11489,7 +11552,8 @@ function generateTestCaseNames(funcName, _type, quality = false) {
|
|
|
11489
11552
|
];
|
|
11490
11553
|
}
|
|
11491
11554
|
function inferFunctionParams(sourceContent, funcName) {
|
|
11492
|
-
if (!sourceContent || !funcName)
|
|
11555
|
+
if (!sourceContent || !funcName)
|
|
11556
|
+
return [];
|
|
11493
11557
|
const patterns = [
|
|
11494
11558
|
new RegExp(`(?:export\\s+)?(?:async\\s+)?function\\s+${funcName}\\s*\\(([^)]*)\\)`, "m"),
|
|
11495
11559
|
new RegExp(`(?:export\\s+)?const\\s+${funcName}\\s*[:=]\\s*(?:async\\s+)?\\(([^)]*)\\)`, "m"),
|
|
@@ -11502,7 +11566,8 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
11502
11566
|
if (m) {
|
|
11503
11567
|
return m[1].split(",").map((s) => {
|
|
11504
11568
|
const trimmed = s.trim();
|
|
11505
|
-
if (!trimmed)
|
|
11569
|
+
if (!trimmed)
|
|
11570
|
+
return null;
|
|
11506
11571
|
const nameMatch = trimmed.match(/^\s*((?:public|protected)|static|final|val|var|let|const)?\s*(?:readonly\s+)?(?:[_$a-zA-Z][_$a-zA-Z0-9]*)\s*(?::|(?=\s*=)|(?=\s*[,)]))/);
|
|
11507
11572
|
const rawName = trimmed.replace(/^[^a-zA-Z_$]*/, "").replace(/[=:].*$/, "").replace(/\s+.*$/, "").trim();
|
|
11508
11573
|
const defaultMatch = trimmed.match(/=\s*(.+)$/);
|
|
@@ -11518,22 +11583,35 @@ function inferFunctionParams(sourceContent, funcName) {
|
|
|
11518
11583
|
return [];
|
|
11519
11584
|
}
|
|
11520
11585
|
function inferTypeFromName(paramName, defaultValue) {
|
|
11521
|
-
if (!paramName)
|
|
11586
|
+
if (!paramName)
|
|
11587
|
+
return "any";
|
|
11522
11588
|
const name = paramName.toLowerCase();
|
|
11523
11589
|
if (defaultValue !== null && defaultValue !== void 0) {
|
|
11524
|
-
if (/^["']/.test(defaultValue))
|
|
11525
|
-
|
|
11526
|
-
if (
|
|
11527
|
-
|
|
11528
|
-
if (
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11532
|
-
|
|
11533
|
-
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
|
|
11590
|
+
if (/^["']/.test(defaultValue))
|
|
11591
|
+
return "string";
|
|
11592
|
+
if (/^\d+\.?\d*$/.test(defaultValue))
|
|
11593
|
+
return "number";
|
|
11594
|
+
if (/^(true|false)$/i.test(defaultValue))
|
|
11595
|
+
return "boolean";
|
|
11596
|
+
if (/^\[/.test(defaultValue))
|
|
11597
|
+
return "array";
|
|
11598
|
+
if (/^\{/.test(defaultValue))
|
|
11599
|
+
return "object";
|
|
11600
|
+
if (/^null$/i.test(defaultValue))
|
|
11601
|
+
return "null";
|
|
11602
|
+
}
|
|
11603
|
+
if (/^(is|has|can|should|will|did|was|are|contains?_|[A-Z])/.test(name))
|
|
11604
|
+
return "boolean";
|
|
11605
|
+
if (/^(count|index|limit|offset|max|min|size|length|total|num|age)_?/.test(name))
|
|
11606
|
+
return "number";
|
|
11607
|
+
if (/^(name|title|label|msg|message|text|str|prefix|suffix|path|url|email|id)_?/.test(name))
|
|
11608
|
+
return "string";
|
|
11609
|
+
if (/^(items|list|arr|entries|data|values|args)_?/.test(name))
|
|
11610
|
+
return "array";
|
|
11611
|
+
if (/^(obj|config|opts|options|settings|params|props)_?/.test(name))
|
|
11612
|
+
return "object";
|
|
11613
|
+
if (/^(fn|cb|callback|handler|on[A-Z])/.test(name))
|
|
11614
|
+
return "function";
|
|
11537
11615
|
return "any";
|
|
11538
11616
|
}
|
|
11539
11617
|
function _langComment(lang) {
|
|
@@ -11546,14 +11624,22 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11546
11624
|
let block = "";
|
|
11547
11625
|
const testValues = params.map((p) => {
|
|
11548
11626
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11549
|
-
if (t === "string" || t === "String")
|
|
11550
|
-
|
|
11551
|
-
if (t === "
|
|
11552
|
-
|
|
11553
|
-
if (t === "
|
|
11554
|
-
|
|
11555
|
-
if (t === "
|
|
11556
|
-
|
|
11627
|
+
if (t === "string" || t === "String")
|
|
11628
|
+
return '"sample_input"';
|
|
11629
|
+
if (t === "number" || t === "int" || t === "float" || t === "Number")
|
|
11630
|
+
return "42";
|
|
11631
|
+
if (t === "boolean" || t === "bool" || t === "Boolean")
|
|
11632
|
+
return "true";
|
|
11633
|
+
if (t === "array" || t === "Array" || t === "list" || t === "List")
|
|
11634
|
+
return "[]";
|
|
11635
|
+
if (t === "object" || t === "Object" || t === "dict" || t === "Dict")
|
|
11636
|
+
return "{}";
|
|
11637
|
+
if (t === "function" || t === "Function")
|
|
11638
|
+
return "() => {}";
|
|
11639
|
+
if (t === "any")
|
|
11640
|
+
return '"test"';
|
|
11641
|
+
if (t === "null")
|
|
11642
|
+
return "null";
|
|
11557
11643
|
return '"test"';
|
|
11558
11644
|
});
|
|
11559
11645
|
const args = testValues.join(", ");
|
|
@@ -11583,8 +11669,10 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11583
11669
|
`;
|
|
11584
11670
|
const ecArgs = params.map((p) => {
|
|
11585
11671
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11586
|
-
if (t === "string")
|
|
11587
|
-
|
|
11672
|
+
if (t === "string")
|
|
11673
|
+
return '""';
|
|
11674
|
+
if (t === "number" || t === "int" || t === "float")
|
|
11675
|
+
return "0";
|
|
11588
11676
|
return '"edge"';
|
|
11589
11677
|
}).join(", ");
|
|
11590
11678
|
block += `${indent} result = ${funcName}(${ecArgs})
|
|
@@ -11622,11 +11710,16 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11622
11710
|
`;
|
|
11623
11711
|
const ecArgsJS = params.map((p) => {
|
|
11624
11712
|
const t = p.type || inferTypeFromName(p.name, p.defaultValue);
|
|
11625
|
-
if (t === "string")
|
|
11626
|
-
|
|
11627
|
-
if (t === "
|
|
11628
|
-
|
|
11629
|
-
if (t === "
|
|
11713
|
+
if (t === "string")
|
|
11714
|
+
return '""';
|
|
11715
|
+
if (t === "number" || t === "int" || t === "float")
|
|
11716
|
+
return "0";
|
|
11717
|
+
if (t === "boolean")
|
|
11718
|
+
return "false";
|
|
11719
|
+
if (t === "array")
|
|
11720
|
+
return "[]";
|
|
11721
|
+
if (t === "object")
|
|
11722
|
+
return "{}";
|
|
11630
11723
|
return "undefined";
|
|
11631
11724
|
}).join(", ");
|
|
11632
11725
|
block += `${indent} const result = mod.${funcName}(${ecArgsJS});
|
|
@@ -11659,14 +11752,15 @@ function buildQualityAssertionsForFunc(funcName, params, lang, indent) {
|
|
|
11659
11752
|
return block;
|
|
11660
11753
|
}
|
|
11661
11754
|
function isSkeletonUseless(content) {
|
|
11662
|
-
if (!content)
|
|
11755
|
+
if (!content)
|
|
11756
|
+
return true;
|
|
11663
11757
|
const lines = content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("//") && !l.trim().startsWith("#") && !l.trim().startsWith("/*") && !l.trim().startsWith("*"));
|
|
11664
11758
|
const todoLines = content.split("\n").filter((l) => /TODO|placeholder|smoke|is exported|module loads/.test(l));
|
|
11665
11759
|
const meaningfulLines = lines.filter((l) => !/TODO|placeholder|smoke|is exported|module loads|throw new Error|raise AssertionError|pytest\.skip|assert.*true/.test(l));
|
|
11666
11760
|
return meaningfulLines.length < 2;
|
|
11667
11761
|
}
|
|
11668
11762
|
|
|
11669
|
-
// src/lib/test-skeletons.
|
|
11763
|
+
// src/lib/test-skeletons.js
|
|
11670
11764
|
var TEST_SKELETONS = {
|
|
11671
11765
|
py: (name, exports = [], depth = "full", strict = true, quality = true, sourceContent = "") => {
|
|
11672
11766
|
const moduleImport = name.replace(/-/g, "_");
|
|
@@ -11694,7 +11788,8 @@ var TEST_SKELETONS = {
|
|
|
11694
11788
|
|
|
11695
11789
|
`;
|
|
11696
11790
|
for (const exp of exports) {
|
|
11697
|
-
if (exp.type === "class")
|
|
11791
|
+
if (exp.type === "class")
|
|
11792
|
+
continue;
|
|
11698
11793
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11699
11794
|
content += `# TODO: implement tests for ${exp.name}
|
|
11700
11795
|
`;
|
|
@@ -11702,10 +11797,12 @@ var TEST_SKELETONS = {
|
|
|
11702
11797
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11703
11798
|
content += `def test_${caseFunc}():
|
|
11704
11799
|
`;
|
|
11705
|
-
if (strict)
|
|
11800
|
+
if (strict)
|
|
11801
|
+
content += ` raise AssertionError("TODO: implement ${caseName}")
|
|
11706
11802
|
|
|
11707
11803
|
`;
|
|
11708
|
-
else
|
|
11804
|
+
else
|
|
11805
|
+
content += ` pytest.skip("TODO: implement ${caseName}")
|
|
11709
11806
|
|
|
11710
11807
|
`;
|
|
11711
11808
|
}
|
|
@@ -11717,10 +11814,12 @@ var TEST_SKELETONS = {
|
|
|
11717
11814
|
if (exports.length === 0) {
|
|
11718
11815
|
content += `def test_${name}_placeholder():
|
|
11719
11816
|
`;
|
|
11720
|
-
if (strict)
|
|
11817
|
+
if (strict)
|
|
11818
|
+
content += ` raise AssertionError("TODO: implement tests for ${name}")
|
|
11721
11819
|
|
|
11722
11820
|
`;
|
|
11723
|
-
else
|
|
11821
|
+
else
|
|
11822
|
+
content += ` pytest.skip("TODO: implement tests for ${name}")
|
|
11724
11823
|
|
|
11725
11824
|
`;
|
|
11726
11825
|
}
|
|
@@ -11754,7 +11853,8 @@ var TEST_SKELETONS = {
|
|
|
11754
11853
|
|
|
11755
11854
|
`;
|
|
11756
11855
|
for (const exp of exports) {
|
|
11757
|
-
if (exp.type === "class")
|
|
11856
|
+
if (exp.type === "class")
|
|
11857
|
+
continue;
|
|
11758
11858
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11759
11859
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11760
11860
|
`;
|
|
@@ -11770,9 +11870,11 @@ var TEST_SKELETONS = {
|
|
|
11770
11870
|
`;
|
|
11771
11871
|
content += ` // TODO: implement ${caseName}
|
|
11772
11872
|
`;
|
|
11773
|
-
if (strict)
|
|
11873
|
+
if (strict)
|
|
11874
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11774
11875
|
`;
|
|
11775
|
-
else
|
|
11876
|
+
else
|
|
11877
|
+
content += ` expect(true).toBe(true);
|
|
11776
11878
|
`;
|
|
11777
11879
|
content += ` });
|
|
11778
11880
|
|
|
@@ -11825,7 +11927,8 @@ var TEST_SKELETONS = {
|
|
|
11825
11927
|
|
|
11826
11928
|
`;
|
|
11827
11929
|
for (const exp of exports) {
|
|
11828
|
-
if (exp.type === "class")
|
|
11930
|
+
if (exp.type === "class")
|
|
11931
|
+
continue;
|
|
11829
11932
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11830
11933
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11831
11934
|
`;
|
|
@@ -11841,9 +11944,11 @@ var TEST_SKELETONS = {
|
|
|
11841
11944
|
`;
|
|
11842
11945
|
content += ` // TODO: implement ${caseName}
|
|
11843
11946
|
`;
|
|
11844
|
-
if (strict)
|
|
11947
|
+
if (strict)
|
|
11948
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11845
11949
|
`;
|
|
11846
|
-
else
|
|
11950
|
+
else
|
|
11951
|
+
content += ` expect(true).toBe(true);
|
|
11847
11952
|
`;
|
|
11848
11953
|
content += ` });
|
|
11849
11954
|
|
|
@@ -11896,7 +12001,8 @@ var TEST_SKELETONS = {
|
|
|
11896
12001
|
|
|
11897
12002
|
`;
|
|
11898
12003
|
for (const exp of exports) {
|
|
11899
|
-
if (exp.type === "class")
|
|
12004
|
+
if (exp.type === "class")
|
|
12005
|
+
continue;
|
|
11900
12006
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11901
12007
|
content += ` // TODO: implement tests for ${exp.name}
|
|
11902
12008
|
`;
|
|
@@ -11912,9 +12018,11 @@ var TEST_SKELETONS = {
|
|
|
11912
12018
|
`;
|
|
11913
12019
|
content += ` // TODO: implement ${caseName}
|
|
11914
12020
|
`;
|
|
11915
|
-
if (strict)
|
|
12021
|
+
if (strict)
|
|
12022
|
+
content += ` throw new Error('TODO: implement ${caseName}');
|
|
11916
12023
|
`;
|
|
11917
|
-
else
|
|
12024
|
+
else
|
|
12025
|
+
content += ` expect(true).toBe(true);
|
|
11918
12026
|
`;
|
|
11919
12027
|
content += ` });
|
|
11920
12028
|
|
|
@@ -11974,7 +12082,8 @@ var TEST_SKELETONS = {
|
|
|
11974
12082
|
|
|
11975
12083
|
`;
|
|
11976
12084
|
for (const exp of exports) {
|
|
11977
|
-
if (exp.type === "class")
|
|
12085
|
+
if (exp.type === "class")
|
|
12086
|
+
continue;
|
|
11978
12087
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
11979
12088
|
const expCap = exp.name.charAt(0).toUpperCase() + exp.name.slice(1);
|
|
11980
12089
|
content += `// TODO: implement tests for ${exp.name}
|
|
@@ -11983,9 +12092,11 @@ var TEST_SKELETONS = {
|
|
|
11983
12092
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
11984
12093
|
content += `func Test${cap}_${caseFunc}(t *testing.T) {
|
|
11985
12094
|
`;
|
|
11986
|
-
if (strict)
|
|
12095
|
+
if (strict)
|
|
12096
|
+
content += ` t.Error("TODO: implement ${caseName}")
|
|
11987
12097
|
`;
|
|
11988
|
-
else
|
|
12098
|
+
else
|
|
12099
|
+
content += ` t.Skip("TODO: implement ${caseName}")
|
|
11989
12100
|
`;
|
|
11990
12101
|
content += `}
|
|
11991
12102
|
|
|
@@ -12005,9 +12116,11 @@ var TEST_SKELETONS = {
|
|
|
12005
12116
|
if (exports.length === 0) {
|
|
12006
12117
|
content += `func Test${cap}_Placeholder(t *testing.T) {
|
|
12007
12118
|
`;
|
|
12008
|
-
if (strict)
|
|
12119
|
+
if (strict)
|
|
12120
|
+
content += ` t.Error("TODO: implement tests for ${name}")
|
|
12009
12121
|
`;
|
|
12010
|
-
else
|
|
12122
|
+
else
|
|
12123
|
+
content += ` t.Skip("TODO: implement tests for ${name}")
|
|
12011
12124
|
`;
|
|
12012
12125
|
content += `}
|
|
12013
12126
|
`;
|
|
@@ -12040,9 +12153,11 @@ var TEST_SKELETONS = {
|
|
|
12040
12153
|
`;
|
|
12041
12154
|
content += ` echo "TODO: implement ${caseName}"
|
|
12042
12155
|
`;
|
|
12043
|
-
if (strict)
|
|
12156
|
+
if (strict)
|
|
12157
|
+
content += ` exit 1
|
|
12044
12158
|
`;
|
|
12045
|
-
else
|
|
12159
|
+
else
|
|
12160
|
+
content += ` echo "SKIP: ${caseName}"
|
|
12046
12161
|
`;
|
|
12047
12162
|
content += `}
|
|
12048
12163
|
|
|
@@ -12056,9 +12171,11 @@ var TEST_SKELETONS = {
|
|
|
12056
12171
|
if (exports.length === 0) {
|
|
12057
12172
|
content += `function test_smoke {
|
|
12058
12173
|
`;
|
|
12059
|
-
if (strict)
|
|
12174
|
+
if (strict)
|
|
12175
|
+
content += ` echo "TODO: implement tests for ${name}" && exit 1
|
|
12060
12176
|
`;
|
|
12061
|
-
else
|
|
12177
|
+
else
|
|
12178
|
+
content += ` echo "TODO: implement tests for ${name}"
|
|
12062
12179
|
`;
|
|
12063
12180
|
content += `}
|
|
12064
12181
|
`;
|
|
@@ -12098,7 +12215,8 @@ mod tests {
|
|
|
12098
12215
|
|
|
12099
12216
|
`;
|
|
12100
12217
|
for (const exp of exports) {
|
|
12101
|
-
if (exp.type === "class")
|
|
12218
|
+
if (exp.type === "class")
|
|
12219
|
+
continue;
|
|
12102
12220
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12103
12221
|
content += ` // TODO: implement tests for ${exp.name}
|
|
12104
12222
|
`;
|
|
@@ -12107,9 +12225,11 @@ mod tests {
|
|
|
12107
12225
|
content += ` #[test]
|
|
12108
12226
|
fn test_${caseFunc}() {
|
|
12109
12227
|
`;
|
|
12110
|
-
if (strict)
|
|
12228
|
+
if (strict)
|
|
12229
|
+
content += ` panic!("TODO: implement ${caseName}");
|
|
12111
12230
|
`;
|
|
12112
|
-
else
|
|
12231
|
+
else
|
|
12232
|
+
content += ` // TODO: implement ${caseName}
|
|
12113
12233
|
`;
|
|
12114
12234
|
content += ` }
|
|
12115
12235
|
|
|
@@ -12124,9 +12244,11 @@ mod tests {
|
|
|
12124
12244
|
content += ` #[test]
|
|
12125
12245
|
fn ${name}_placeholder() {
|
|
12126
12246
|
`;
|
|
12127
|
-
if (strict)
|
|
12247
|
+
if (strict)
|
|
12248
|
+
content += ` panic!("TODO: implement tests for ${name}");
|
|
12128
12249
|
`;
|
|
12129
|
-
else
|
|
12250
|
+
else
|
|
12251
|
+
content += ` // TODO: implement tests for ${name}
|
|
12130
12252
|
`;
|
|
12131
12253
|
content += ` }
|
|
12132
12254
|
`;
|
|
@@ -12166,7 +12288,8 @@ mod tests {
|
|
|
12166
12288
|
|
|
12167
12289
|
`;
|
|
12168
12290
|
for (const exp of exports) {
|
|
12169
|
-
if (exp.type === "class")
|
|
12291
|
+
if (exp.type === "class")
|
|
12292
|
+
continue;
|
|
12170
12293
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12171
12294
|
content += ` # TODO: implement tests for ${exp.name}
|
|
12172
12295
|
`;
|
|
@@ -12174,9 +12297,11 @@ mod tests {
|
|
|
12174
12297
|
const caseFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12175
12298
|
content += ` def test_${caseFunc}
|
|
12176
12299
|
`;
|
|
12177
|
-
if (strict)
|
|
12300
|
+
if (strict)
|
|
12301
|
+
content += ` flunk "TODO: implement ${caseName}"
|
|
12178
12302
|
`;
|
|
12179
|
-
else
|
|
12303
|
+
else
|
|
12304
|
+
content += ` # TODO: implement ${caseName}
|
|
12180
12305
|
`;
|
|
12181
12306
|
content += ` end
|
|
12182
12307
|
|
|
@@ -12190,9 +12315,11 @@ mod tests {
|
|
|
12190
12315
|
if (exports.length === 0) {
|
|
12191
12316
|
content += ` def test_placeholder
|
|
12192
12317
|
`;
|
|
12193
|
-
if (strict)
|
|
12318
|
+
if (strict)
|
|
12319
|
+
content += ` flunk "TODO: implement tests for ${name}"
|
|
12194
12320
|
`;
|
|
12195
|
-
else
|
|
12321
|
+
else
|
|
12322
|
+
content += ` # TODO: implement tests for ${name}
|
|
12196
12323
|
`;
|
|
12197
12324
|
content += ` end
|
|
12198
12325
|
`;
|
|
@@ -12238,15 +12365,18 @@ mod tests {
|
|
|
12238
12365
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12239
12366
|
for (const caseName of cases) {
|
|
12240
12367
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12241
|
-
if (!strict)
|
|
12368
|
+
if (!strict)
|
|
12369
|
+
content += ` // @Disabled("TODO")
|
|
12242
12370
|
`;
|
|
12243
12371
|
content += ` @Test
|
|
12244
12372
|
`;
|
|
12245
12373
|
content += ` void test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
12246
12374
|
`;
|
|
12247
|
-
if (strict)
|
|
12375
|
+
if (strict)
|
|
12376
|
+
content += ` fail("TODO: implement ${caseName}");
|
|
12248
12377
|
`;
|
|
12249
|
-
else
|
|
12378
|
+
else
|
|
12379
|
+
content += ` assertTrue(true); // TODO: implement ${caseName}
|
|
12250
12380
|
`;
|
|
12251
12381
|
content += ` }
|
|
12252
12382
|
|
|
@@ -12308,15 +12438,18 @@ mod tests {
|
|
|
12308
12438
|
const cases = generateTestCaseNames(exp.name, exp.type, quality);
|
|
12309
12439
|
for (const caseName of cases) {
|
|
12310
12440
|
const testFunc = caseName.replace(/[^a-zA-Z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
12311
|
-
if (!strict)
|
|
12441
|
+
if (!strict)
|
|
12442
|
+
content += ` // @Disabled("TODO")
|
|
12312
12443
|
`;
|
|
12313
12444
|
content += ` @Test
|
|
12314
12445
|
`;
|
|
12315
12446
|
content += ` fun test${testFunc.charAt(0).toUpperCase() + testFunc.slice(1)}() {
|
|
12316
12447
|
`;
|
|
12317
|
-
if (strict)
|
|
12448
|
+
if (strict)
|
|
12449
|
+
content += ` fail("TODO: implement ${caseName}")
|
|
12318
12450
|
`;
|
|
12319
|
-
else
|
|
12451
|
+
else
|
|
12452
|
+
content += ` assertTrue(true) // TODO: implement ${caseName}
|
|
12320
12453
|
`;
|
|
12321
12454
|
content += ` }
|
|
12322
12455
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibeostheog",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.15",
|
|
4
4
|
"description": "Cost-aware delegation enforcer for OpenCode. Tracks model usage, routes Task subagents to cheaper tiers, surfaces cumulative savings in chat. Includes research audit, reporting framework, project memory, progressive scratchpad decadence, and trinity CLI for brain/medium/cheap slot switching.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"release": "node scripts/release.mjs",
|