majlis 0.6.0 → 0.6.1
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/cli.js +125 -51
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1903,6 +1903,16 @@ function truncateContext(content, limit) {
|
|
|
1903
1903
|
if (content.length <= limit) return content;
|
|
1904
1904
|
return content.slice(0, limit) + "\n[TRUNCATED]";
|
|
1905
1905
|
}
|
|
1906
|
+
function readLatestDiagnosis(projectRoot) {
|
|
1907
|
+
const dir = path3.join(projectRoot, "docs", "diagnosis");
|
|
1908
|
+
try {
|
|
1909
|
+
const files = fs3.readdirSync(dir).filter((f) => f.startsWith("diagnosis-") && f.endsWith(".md")).sort().reverse();
|
|
1910
|
+
if (files.length === 0) return "";
|
|
1911
|
+
return fs3.readFileSync(path3.join(dir, files[0]), "utf-8");
|
|
1912
|
+
} catch {
|
|
1913
|
+
return "";
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1906
1916
|
var fs3, path3, DEFAULT_CONFIG2, _cachedConfig, _cachedRoot, CONTEXT_LIMITS;
|
|
1907
1917
|
var init_config = __esm({
|
|
1908
1918
|
"src/config.ts"() {
|
|
@@ -2417,8 +2427,10 @@ ${taskPrompt}`;
|
|
|
2417
2427
|
}
|
|
2418
2428
|
return { output: markdown, structured, truncated };
|
|
2419
2429
|
}
|
|
2420
|
-
async function spawnSynthesiser(context, projectRoot) {
|
|
2430
|
+
async function spawnSynthesiser(context, projectRoot, opts) {
|
|
2421
2431
|
const root = projectRoot ?? findProjectRoot() ?? process.cwd();
|
|
2432
|
+
const maxTurns = opts?.maxTurns ?? 5;
|
|
2433
|
+
const tools = opts?.tools ?? ["Read", "Glob", "Grep"];
|
|
2422
2434
|
const contextJson = JSON.stringify(context);
|
|
2423
2435
|
const taskPrompt = context.taskPrompt ?? "Synthesise the findings into actionable builder guidance.";
|
|
2424
2436
|
const prompt = `Here is your context:
|
|
@@ -2429,14 +2441,14 @@ ${contextJson}
|
|
|
2429
2441
|
|
|
2430
2442
|
${taskPrompt}`;
|
|
2431
2443
|
const systemPrompt = 'You are a Synthesis Agent. Be concrete: which decisions failed, which assumptions broke, what constraints must the next approach satisfy. CRITICAL: Your LAST line of output MUST be a <!-- majlis-json --> block. The framework parses this programmatically \u2014 if you omit it, the pipeline breaks. Format: <!-- majlis-json {"guidance": "your guidance here"} -->';
|
|
2432
|
-
console.log(`[synthesiser] Spawning (maxTurns:
|
|
2444
|
+
console.log(`[synthesiser] Spawning (maxTurns: ${maxTurns})...`);
|
|
2433
2445
|
const { text: markdown, costUsd, truncated } = await runQuery({
|
|
2434
2446
|
prompt,
|
|
2435
2447
|
model: "sonnet",
|
|
2436
|
-
tools
|
|
2448
|
+
tools,
|
|
2437
2449
|
systemPrompt,
|
|
2438
2450
|
cwd: root,
|
|
2439
|
-
maxTurns
|
|
2451
|
+
maxTurns,
|
|
2440
2452
|
label: "synthesiser",
|
|
2441
2453
|
role: "synthesiser"
|
|
2442
2454
|
});
|
|
@@ -2663,6 +2675,38 @@ var init_spawn = __esm({
|
|
|
2663
2675
|
}
|
|
2664
2676
|
});
|
|
2665
2677
|
|
|
2678
|
+
// src/git.ts
|
|
2679
|
+
function autoCommit(root, message) {
|
|
2680
|
+
try {
|
|
2681
|
+
(0, import_node_child_process.execSync)("git add docs/ .majlis/scripts/ 2>/dev/null; true", {
|
|
2682
|
+
cwd: root,
|
|
2683
|
+
encoding: "utf-8",
|
|
2684
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2685
|
+
});
|
|
2686
|
+
const diff = (0, import_node_child_process.execSync)("git diff --cached --stat", {
|
|
2687
|
+
cwd: root,
|
|
2688
|
+
encoding: "utf-8",
|
|
2689
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2690
|
+
}).trim();
|
|
2691
|
+
if (!diff) return;
|
|
2692
|
+
(0, import_node_child_process.execSync)(`git commit -m ${JSON.stringify(`[majlis] ${message}`)}`, {
|
|
2693
|
+
cwd: root,
|
|
2694
|
+
encoding: "utf-8",
|
|
2695
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2696
|
+
});
|
|
2697
|
+
info(`Auto-committed: ${message}`);
|
|
2698
|
+
} catch {
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
var import_node_child_process;
|
|
2702
|
+
var init_git = __esm({
|
|
2703
|
+
"src/git.ts"() {
|
|
2704
|
+
"use strict";
|
|
2705
|
+
import_node_child_process = require("child_process");
|
|
2706
|
+
init_format();
|
|
2707
|
+
}
|
|
2708
|
+
});
|
|
2709
|
+
|
|
2666
2710
|
// src/metrics.ts
|
|
2667
2711
|
function compareMetrics(db, experimentId, config) {
|
|
2668
2712
|
const before = getMetricsByExperimentAndPhase(db, experimentId, "before");
|
|
@@ -2752,7 +2796,7 @@ async function captureMetrics(phase, args) {
|
|
|
2752
2796
|
if (config.build.pre_measure) {
|
|
2753
2797
|
info(`Running pre-measure: ${config.build.pre_measure}`);
|
|
2754
2798
|
try {
|
|
2755
|
-
(0,
|
|
2799
|
+
(0, import_node_child_process2.execSync)(config.build.pre_measure, { cwd: root, encoding: "utf-8", stdio: "inherit" });
|
|
2756
2800
|
} catch {
|
|
2757
2801
|
warn("Pre-measure command failed \u2014 continuing anyway.");
|
|
2758
2802
|
}
|
|
@@ -2763,7 +2807,7 @@ async function captureMetrics(phase, args) {
|
|
|
2763
2807
|
info(`Running metrics: ${config.metrics.command}`);
|
|
2764
2808
|
let metricsOutput;
|
|
2765
2809
|
try {
|
|
2766
|
-
metricsOutput = (0,
|
|
2810
|
+
metricsOutput = (0, import_node_child_process2.execSync)(config.metrics.command, {
|
|
2767
2811
|
cwd: root,
|
|
2768
2812
|
encoding: "utf-8",
|
|
2769
2813
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -2782,7 +2826,7 @@ async function captureMetrics(phase, args) {
|
|
|
2782
2826
|
success(`Captured ${parsed.length} metric(s) for ${exp.slug} (phase: ${phase})`);
|
|
2783
2827
|
if (config.build.post_measure) {
|
|
2784
2828
|
try {
|
|
2785
|
-
(0,
|
|
2829
|
+
(0, import_node_child_process2.execSync)(config.build.post_measure, { cwd: root, encoding: "utf-8", stdio: "inherit" });
|
|
2786
2830
|
} catch {
|
|
2787
2831
|
warn("Post-measure command failed.");
|
|
2788
2832
|
}
|
|
@@ -2833,11 +2877,11 @@ function formatDelta(delta) {
|
|
|
2833
2877
|
const prefix = delta > 0 ? "+" : "";
|
|
2834
2878
|
return `${prefix}${delta.toFixed(4)}`;
|
|
2835
2879
|
}
|
|
2836
|
-
var
|
|
2880
|
+
var import_node_child_process2;
|
|
2837
2881
|
var init_measure = __esm({
|
|
2838
2882
|
"src/commands/measure.ts"() {
|
|
2839
2883
|
"use strict";
|
|
2840
|
-
|
|
2884
|
+
import_node_child_process2 = require("child_process");
|
|
2841
2885
|
init_connection();
|
|
2842
2886
|
init_queries();
|
|
2843
2887
|
init_metrics();
|
|
@@ -2870,7 +2914,7 @@ async function newExperiment(args) {
|
|
|
2870
2914
|
const paddedNum = String(num).padStart(3, "0");
|
|
2871
2915
|
const branch = `exp/${paddedNum}-${slug}`;
|
|
2872
2916
|
try {
|
|
2873
|
-
(0,
|
|
2917
|
+
(0, import_node_child_process3.execSync)(`git checkout -b ${branch}`, {
|
|
2874
2918
|
cwd: root,
|
|
2875
2919
|
encoding: "utf-8",
|
|
2876
2920
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -2891,6 +2935,7 @@ async function newExperiment(args) {
|
|
|
2891
2935
|
fs5.writeFileSync(logPath, logContent);
|
|
2892
2936
|
info(`Created experiment log: docs/experiments/${paddedNum}-${slug}.md`);
|
|
2893
2937
|
}
|
|
2938
|
+
autoCommit(root, `new: ${slug}`);
|
|
2894
2939
|
if (config.cycle.auto_baseline_on_new_experiment && config.metrics.command) {
|
|
2895
2940
|
info("Auto-baselining... (run `majlis baseline` to do this manually)");
|
|
2896
2941
|
try {
|
|
@@ -2927,12 +2972,12 @@ async function revert(args) {
|
|
|
2927
2972
|
);
|
|
2928
2973
|
updateExperimentStatus(db, exp.id, "dead_end");
|
|
2929
2974
|
try {
|
|
2930
|
-
const currentBranch = (0,
|
|
2975
|
+
const currentBranch = (0, import_node_child_process3.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
2931
2976
|
cwd: root,
|
|
2932
2977
|
encoding: "utf-8"
|
|
2933
2978
|
}).trim();
|
|
2934
2979
|
if (currentBranch === exp.branch) {
|
|
2935
|
-
(0,
|
|
2980
|
+
(0, import_node_child_process3.execSync)("git checkout main 2>/dev/null || git checkout master", {
|
|
2936
2981
|
cwd: root,
|
|
2937
2982
|
encoding: "utf-8",
|
|
2938
2983
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -2943,17 +2988,18 @@ async function revert(args) {
|
|
|
2943
2988
|
}
|
|
2944
2989
|
info(`Experiment ${exp.slug} reverted to dead-end. Reason: ${reason}`);
|
|
2945
2990
|
}
|
|
2946
|
-
var fs5, path5,
|
|
2991
|
+
var fs5, path5, import_node_child_process3;
|
|
2947
2992
|
var init_experiment = __esm({
|
|
2948
2993
|
"src/commands/experiment.ts"() {
|
|
2949
2994
|
"use strict";
|
|
2950
2995
|
fs5 = __toESM(require("fs"));
|
|
2951
2996
|
path5 = __toESM(require("path"));
|
|
2952
|
-
|
|
2997
|
+
import_node_child_process3 = require("child_process");
|
|
2953
2998
|
init_connection();
|
|
2954
2999
|
init_queries();
|
|
2955
3000
|
init_config();
|
|
2956
3001
|
init_spawn();
|
|
3002
|
+
init_git();
|
|
2957
3003
|
init_format();
|
|
2958
3004
|
}
|
|
2959
3005
|
});
|
|
@@ -3301,6 +3347,7 @@ async function resolve(db, exp, projectRoot) {
|
|
|
3301
3347
|
gitMerge(exp.branch, projectRoot);
|
|
3302
3348
|
const gaps = grades.filter((g) => g.grade === "good").map((g) => `- **${g.component}**: ${g.notes ?? "minor gaps"}`).join("\n");
|
|
3303
3349
|
appendToFragilityMap(projectRoot, exp.slug, gaps);
|
|
3350
|
+
autoCommit(projectRoot, `resolve: fragility gaps from ${exp.slug}`);
|
|
3304
3351
|
updateExperimentStatus(db, exp.id, "merged");
|
|
3305
3352
|
success(`Experiment ${exp.slug} MERGED (good, ${grades.filter((g) => g.grade === "good").length} gaps added to fragility map).`);
|
|
3306
3353
|
break;
|
|
@@ -3435,7 +3482,12 @@ async function resolveDbOnly(db, exp, projectRoot) {
|
|
|
3435
3482
|
}
|
|
3436
3483
|
function gitMerge(branch, cwd) {
|
|
3437
3484
|
try {
|
|
3438
|
-
(0,
|
|
3485
|
+
(0, import_node_child_process4.execSync)("git checkout main 2>/dev/null || git checkout master", {
|
|
3486
|
+
cwd,
|
|
3487
|
+
encoding: "utf-8",
|
|
3488
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
3489
|
+
});
|
|
3490
|
+
(0, import_node_child_process4.execSync)(`git merge ${branch} --no-ff -m "Merge experiment branch ${branch}"`, {
|
|
3439
3491
|
cwd,
|
|
3440
3492
|
encoding: "utf-8",
|
|
3441
3493
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -3446,16 +3498,16 @@ function gitMerge(branch, cwd) {
|
|
|
3446
3498
|
}
|
|
3447
3499
|
function gitRevert(branch, cwd) {
|
|
3448
3500
|
try {
|
|
3449
|
-
const currentBranch = (0,
|
|
3501
|
+
const currentBranch = (0, import_node_child_process4.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
3450
3502
|
cwd,
|
|
3451
3503
|
encoding: "utf-8"
|
|
3452
3504
|
}).trim();
|
|
3453
3505
|
if (currentBranch === branch) {
|
|
3454
3506
|
try {
|
|
3455
|
-
(0,
|
|
3507
|
+
(0, import_node_child_process4.execSync)("git checkout -- .", { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
3456
3508
|
} catch {
|
|
3457
3509
|
}
|
|
3458
|
-
(0,
|
|
3510
|
+
(0, import_node_child_process4.execSync)("git checkout main 2>/dev/null || git checkout master", {
|
|
3459
3511
|
cwd,
|
|
3460
3512
|
encoding: "utf-8",
|
|
3461
3513
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -3477,7 +3529,7 @@ ${gaps}
|
|
|
3477
3529
|
`;
|
|
3478
3530
|
fs7.writeFileSync(fragPath, content + entry);
|
|
3479
3531
|
}
|
|
3480
|
-
var fs7, path7,
|
|
3532
|
+
var fs7, path7, import_node_child_process4;
|
|
3481
3533
|
var init_resolve = __esm({
|
|
3482
3534
|
"src/resolve.ts"() {
|
|
3483
3535
|
"use strict";
|
|
@@ -3486,7 +3538,8 @@ var init_resolve = __esm({
|
|
|
3486
3538
|
init_types2();
|
|
3487
3539
|
init_queries();
|
|
3488
3540
|
init_spawn();
|
|
3489
|
-
|
|
3541
|
+
import_node_child_process4 = require("child_process");
|
|
3542
|
+
init_git();
|
|
3490
3543
|
init_format();
|
|
3491
3544
|
}
|
|
3492
3545
|
});
|
|
@@ -3605,7 +3658,7 @@ async function doBuild(db, exp, root) {
|
|
|
3605
3658
|
const existingBaseline = getMetricsByExperimentAndPhase(db, exp.id, "before");
|
|
3606
3659
|
if (config.metrics?.command && existingBaseline.length === 0) {
|
|
3607
3660
|
try {
|
|
3608
|
-
const output = (0,
|
|
3661
|
+
const output = (0, import_node_child_process5.execSync)(config.metrics.command, {
|
|
3609
3662
|
cwd: root,
|
|
3610
3663
|
encoding: "utf-8",
|
|
3611
3664
|
timeout: 6e4,
|
|
@@ -3662,7 +3715,7 @@ Build the experiment: ${exp.hypothesis}` : `Build the experiment: ${exp.hypothes
|
|
|
3662
3715
|
} else {
|
|
3663
3716
|
if (config.metrics?.command) {
|
|
3664
3717
|
try {
|
|
3665
|
-
const output = (0,
|
|
3718
|
+
const output = (0, import_node_child_process5.execSync)(config.metrics.command, {
|
|
3666
3719
|
cwd: root,
|
|
3667
3720
|
encoding: "utf-8",
|
|
3668
3721
|
timeout: 6e4,
|
|
@@ -3686,7 +3739,7 @@ async function doChallenge(db, exp, root) {
|
|
|
3686
3739
|
transition(exp.status, "challenged" /* CHALLENGED */);
|
|
3687
3740
|
let gitDiff = "";
|
|
3688
3741
|
try {
|
|
3689
|
-
gitDiff = (0,
|
|
3742
|
+
gitDiff = (0, import_node_child_process5.execSync)('git diff main -- . ":!.majlis/"', {
|
|
3690
3743
|
cwd: root,
|
|
3691
3744
|
encoding: "utf-8",
|
|
3692
3745
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -3898,12 +3951,13 @@ async function doCompress(db, root) {
|
|
|
3898
3951
|
}, root);
|
|
3899
3952
|
const sizeAfter = fs8.existsSync(synthesisPath) ? fs8.statSync(synthesisPath).size : 0;
|
|
3900
3953
|
recordCompression(db, sessionCount, sizeBefore, sizeAfter);
|
|
3954
|
+
autoCommit(root, "compress: update synthesis");
|
|
3901
3955
|
success(`Compression complete. Synthesis: ${sizeBefore}B \u2192 ${sizeAfter}B`);
|
|
3902
3956
|
}
|
|
3903
3957
|
function gitCommitBuild(exp, cwd) {
|
|
3904
3958
|
try {
|
|
3905
|
-
(0,
|
|
3906
|
-
const diff = (0,
|
|
3959
|
+
(0, import_node_child_process5.execSync)('git add -A -- ":!.majlis/"', { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
3960
|
+
const diff = (0, import_node_child_process5.execSync)("git diff --cached --stat", { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
3907
3961
|
if (!diff) {
|
|
3908
3962
|
info("No code changes to commit.");
|
|
3909
3963
|
return;
|
|
@@ -3911,7 +3965,7 @@ function gitCommitBuild(exp, cwd) {
|
|
|
3911
3965
|
const msg = `EXP-${String(exp.id).padStart(3, "0")}: ${exp.slug}
|
|
3912
3966
|
|
|
3913
3967
|
${exp.hypothesis ?? ""}`;
|
|
3914
|
-
(0,
|
|
3968
|
+
(0, import_node_child_process5.execSync)(`git commit -m ${JSON.stringify(msg)}`, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
3915
3969
|
info(`Committed builder changes on ${exp.branch}.`);
|
|
3916
3970
|
} catch {
|
|
3917
3971
|
warn("Could not auto-commit builder changes \u2014 commit manually before resolving.");
|
|
@@ -3987,13 +4041,13 @@ function ingestStructuredOutput(db, experimentId, structured) {
|
|
|
3987
4041
|
info(`Ingested ${structured.findings.length} finding(s)`);
|
|
3988
4042
|
}
|
|
3989
4043
|
}
|
|
3990
|
-
var fs8, path8,
|
|
4044
|
+
var fs8, path8, import_node_child_process5;
|
|
3991
4045
|
var init_cycle = __esm({
|
|
3992
4046
|
"src/commands/cycle.ts"() {
|
|
3993
4047
|
"use strict";
|
|
3994
4048
|
fs8 = __toESM(require("fs"));
|
|
3995
4049
|
path8 = __toESM(require("path"));
|
|
3996
|
-
|
|
4050
|
+
import_node_child_process5 = require("child_process");
|
|
3997
4051
|
init_connection();
|
|
3998
4052
|
init_queries();
|
|
3999
4053
|
init_machine();
|
|
@@ -4002,6 +4056,7 @@ var init_cycle = __esm({
|
|
|
4002
4056
|
init_resolve();
|
|
4003
4057
|
init_config();
|
|
4004
4058
|
init_metrics();
|
|
4059
|
+
init_git();
|
|
4005
4060
|
init_format();
|
|
4006
4061
|
}
|
|
4007
4062
|
});
|
|
@@ -4035,6 +4090,7 @@ ${deadEnds}
|
|
|
4035
4090
|
|
|
4036
4091
|
Write the classification to docs/classification/ following the template.`
|
|
4037
4092
|
}, root);
|
|
4093
|
+
autoCommit(root, `classify: ${domain.slice(0, 60)}`);
|
|
4038
4094
|
success("Classification complete. Check docs/classification/ for the output.");
|
|
4039
4095
|
}
|
|
4040
4096
|
async function reframe(args) {
|
|
@@ -4077,6 +4133,7 @@ ${deadEnds}
|
|
|
4077
4133
|
Independently propose a decomposition. Compare with the existing classification. Flag structural divergences \u2014 these are the most valuable signals.
|
|
4078
4134
|
Write to docs/reframes/.`
|
|
4079
4135
|
}, root);
|
|
4136
|
+
autoCommit(root, `reframe: ${target.slice(0, 60)}`);
|
|
4080
4137
|
success("Reframe complete. Check docs/reframes/ for the output.");
|
|
4081
4138
|
}
|
|
4082
4139
|
var fs9, path9;
|
|
@@ -4087,6 +4144,7 @@ var init_classify = __esm({
|
|
|
4087
4144
|
path9 = __toESM(require("path"));
|
|
4088
4145
|
init_connection();
|
|
4089
4146
|
init_spawn();
|
|
4147
|
+
init_git();
|
|
4090
4148
|
init_format();
|
|
4091
4149
|
}
|
|
4092
4150
|
});
|
|
@@ -4398,6 +4456,7 @@ async function run(args) {
|
|
|
4398
4456
|
usedHypotheses.add(hypothesis);
|
|
4399
4457
|
info(`Next hypothesis: ${hypothesis}`);
|
|
4400
4458
|
exp = await createNewExperiment(db, root, hypothesis);
|
|
4459
|
+
autoCommit(root, `new: ${exp.slug}`);
|
|
4401
4460
|
success(`Created experiment #${exp.id}: ${exp.slug}`);
|
|
4402
4461
|
}
|
|
4403
4462
|
if (isTerminal(exp.status)) {
|
|
@@ -4449,12 +4508,13 @@ async function deriveNextHypothesis(goal, root, db) {
|
|
|
4449
4508
|
const synthesis = truncateContext(readFileOrEmpty(path11.join(root, "docs", "synthesis", "current.md")), CONTEXT_LIMITS.synthesis);
|
|
4450
4509
|
const fragility = truncateContext(readFileOrEmpty(path11.join(root, "docs", "synthesis", "fragility.md")), CONTEXT_LIMITS.fragility);
|
|
4451
4510
|
const deadEndsDoc = truncateContext(readFileOrEmpty(path11.join(root, "docs", "synthesis", "dead-ends.md")), CONTEXT_LIMITS.deadEnds);
|
|
4511
|
+
const diagnosis = truncateContext(readLatestDiagnosis(root), CONTEXT_LIMITS.synthesis);
|
|
4452
4512
|
const deadEnds = listAllDeadEnds(db);
|
|
4453
4513
|
const config = loadConfig(root);
|
|
4454
4514
|
let metricsOutput = "";
|
|
4455
4515
|
if (config.metrics?.command) {
|
|
4456
4516
|
try {
|
|
4457
|
-
metricsOutput = (0,
|
|
4517
|
+
metricsOutput = (0, import_node_child_process6.execSync)(config.metrics.command, {
|
|
4458
4518
|
cwd: root,
|
|
4459
4519
|
encoding: "utf-8",
|
|
4460
4520
|
timeout: 6e4,
|
|
@@ -4469,7 +4529,10 @@ async function deriveNextHypothesis(goal, root, db) {
|
|
|
4469
4529
|
|
|
4470
4530
|
## Goal
|
|
4471
4531
|
${goal}
|
|
4472
|
-
|
|
4532
|
+
${diagnosis ? `
|
|
4533
|
+
## Latest Diagnosis Report (PRIORITISE \u2014 deep analysis from diagnostician agent)
|
|
4534
|
+
${diagnosis}
|
|
4535
|
+
` : ""}
|
|
4473
4536
|
## Current Metrics
|
|
4474
4537
|
${metricsOutput || "(no metrics configured)"}
|
|
4475
4538
|
|
|
@@ -4489,6 +4552,8 @@ Note: [structural] dead ends are HARD CONSTRAINTS \u2014 your hypothesis MUST NO
|
|
|
4489
4552
|
[procedural] dead ends are process failures \u2014 the approach may still be valid if executed differently.
|
|
4490
4553
|
|
|
4491
4554
|
## Your Task
|
|
4555
|
+
DO NOT read source code or use tools. All context you need is above. Plan from the synthesis and dead-end registry.
|
|
4556
|
+
|
|
4492
4557
|
1. Assess: based on the metrics and synthesis, has the goal been met? Be specific.
|
|
4493
4558
|
2. If YES \u2014 output the JSON block below with goal_met: true.
|
|
4494
4559
|
3. If NO \u2014 propose the SINGLE most promising next experiment hypothesis.
|
|
@@ -4504,7 +4569,7 @@ CRITICAL: Your LAST line of output MUST be EXACTLY this format (on its own line,
|
|
|
4504
4569
|
|
|
4505
4570
|
If the goal is met:
|
|
4506
4571
|
<!-- majlis-json {"goal_met": true, "hypothesis": null} -->`
|
|
4507
|
-
}, root);
|
|
4572
|
+
}, root, { maxTurns: 2, tools: [] });
|
|
4508
4573
|
const structured = result.structured;
|
|
4509
4574
|
if (structured?.goal_met === true) {
|
|
4510
4575
|
return null;
|
|
@@ -4530,7 +4595,7 @@ If the goal is met:
|
|
|
4530
4595
|
${result.output.slice(-2e3)}
|
|
4531
4596
|
|
|
4532
4597
|
<!-- majlis-json {"goal_met": false, "hypothesis": "your hypothesis"} -->`
|
|
4533
|
-
}, root);
|
|
4598
|
+
}, root, { maxTurns: 1, tools: [] });
|
|
4534
4599
|
if (retry.structured?.hypothesis) return retry.structured.hypothesis;
|
|
4535
4600
|
warn("Could not extract hypothesis. Using goal as fallback.");
|
|
4536
4601
|
return goal;
|
|
@@ -4548,7 +4613,7 @@ async function createNewExperiment(db, root, hypothesis) {
|
|
|
4548
4613
|
const paddedNum = String(num).padStart(3, "0");
|
|
4549
4614
|
const branch = `exp/${paddedNum}-${finalSlug}`;
|
|
4550
4615
|
try {
|
|
4551
|
-
(0,
|
|
4616
|
+
(0, import_node_child_process6.execSync)(`git checkout -b ${branch}`, {
|
|
4552
4617
|
cwd: root,
|
|
4553
4618
|
encoding: "utf-8",
|
|
4554
4619
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4571,13 +4636,13 @@ async function createNewExperiment(db, root, hypothesis) {
|
|
|
4571
4636
|
}
|
|
4572
4637
|
return exp;
|
|
4573
4638
|
}
|
|
4574
|
-
var fs11, path11,
|
|
4639
|
+
var fs11, path11, import_node_child_process6;
|
|
4575
4640
|
var init_run = __esm({
|
|
4576
4641
|
"src/commands/run.ts"() {
|
|
4577
4642
|
"use strict";
|
|
4578
4643
|
fs11 = __toESM(require("fs"));
|
|
4579
4644
|
path11 = __toESM(require("path"));
|
|
4580
|
-
|
|
4645
|
+
import_node_child_process6 = require("child_process");
|
|
4581
4646
|
init_connection();
|
|
4582
4647
|
init_queries();
|
|
4583
4648
|
init_machine();
|
|
@@ -4586,6 +4651,7 @@ var init_run = __esm({
|
|
|
4586
4651
|
init_spawn();
|
|
4587
4652
|
init_config();
|
|
4588
4653
|
init_shutdown();
|
|
4654
|
+
init_git();
|
|
4589
4655
|
init_format();
|
|
4590
4656
|
}
|
|
4591
4657
|
});
|
|
@@ -4596,7 +4662,7 @@ function createWorktree(mainRoot, slug, paddedNum) {
|
|
|
4596
4662
|
const worktreeName = `${projectName}-swarm-${paddedNum}-${slug}`;
|
|
4597
4663
|
const worktreePath = path12.join(path12.dirname(mainRoot), worktreeName);
|
|
4598
4664
|
const branch = `swarm/${paddedNum}-${slug}`;
|
|
4599
|
-
(0,
|
|
4665
|
+
(0, import_node_child_process7.execSync)(`git worktree add ${JSON.stringify(worktreePath)} -b ${branch}`, {
|
|
4600
4666
|
cwd: mainRoot,
|
|
4601
4667
|
encoding: "utf-8",
|
|
4602
4668
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4647,7 +4713,7 @@ function initializeWorktree(mainRoot, worktreePath) {
|
|
|
4647
4713
|
}
|
|
4648
4714
|
function cleanupWorktree(mainRoot, wt) {
|
|
4649
4715
|
try {
|
|
4650
|
-
(0,
|
|
4716
|
+
(0, import_node_child_process7.execSync)(`git worktree remove ${JSON.stringify(wt.path)} --force`, {
|
|
4651
4717
|
cwd: mainRoot,
|
|
4652
4718
|
encoding: "utf-8",
|
|
4653
4719
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4656,7 +4722,7 @@ function cleanupWorktree(mainRoot, wt) {
|
|
|
4656
4722
|
warn(`Could not remove worktree ${wt.path} \u2014 remove manually.`);
|
|
4657
4723
|
}
|
|
4658
4724
|
try {
|
|
4659
|
-
(0,
|
|
4725
|
+
(0, import_node_child_process7.execSync)(`git branch -D ${wt.branch}`, {
|
|
4660
4726
|
cwd: mainRoot,
|
|
4661
4727
|
encoding: "utf-8",
|
|
4662
4728
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4664,7 +4730,7 @@ function cleanupWorktree(mainRoot, wt) {
|
|
|
4664
4730
|
} catch {
|
|
4665
4731
|
}
|
|
4666
4732
|
try {
|
|
4667
|
-
(0,
|
|
4733
|
+
(0, import_node_child_process7.execSync)("git worktree prune", {
|
|
4668
4734
|
cwd: mainRoot,
|
|
4669
4735
|
encoding: "utf-8",
|
|
4670
4736
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -4672,13 +4738,13 @@ function cleanupWorktree(mainRoot, wt) {
|
|
|
4672
4738
|
} catch {
|
|
4673
4739
|
}
|
|
4674
4740
|
}
|
|
4675
|
-
var fs12, path12,
|
|
4741
|
+
var fs12, path12, import_node_child_process7;
|
|
4676
4742
|
var init_worktree = __esm({
|
|
4677
4743
|
"src/swarm/worktree.ts"() {
|
|
4678
4744
|
"use strict";
|
|
4679
4745
|
fs12 = __toESM(require("fs"));
|
|
4680
4746
|
path12 = __toESM(require("path"));
|
|
4681
|
-
|
|
4747
|
+
import_node_child_process7 = require("child_process");
|
|
4682
4748
|
init_connection();
|
|
4683
4749
|
init_format();
|
|
4684
4750
|
}
|
|
@@ -4983,7 +5049,7 @@ async function swarm(args) {
|
|
|
4983
5049
|
MAX_PARALLEL
|
|
4984
5050
|
);
|
|
4985
5051
|
try {
|
|
4986
|
-
const status2 = (0,
|
|
5052
|
+
const status2 = (0, import_node_child_process8.execSync)("git status --porcelain", {
|
|
4987
5053
|
cwd: root,
|
|
4988
5054
|
encoding: "utf-8",
|
|
4989
5055
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -5067,7 +5133,7 @@ async function swarm(args) {
|
|
|
5067
5133
|
const best = summary.bestExperiment;
|
|
5068
5134
|
info(`Best experiment: ${best.worktree.slug} (${best.overallGrade})`);
|
|
5069
5135
|
try {
|
|
5070
|
-
(0,
|
|
5136
|
+
(0, import_node_child_process8.execSync)(
|
|
5071
5137
|
`git merge ${best.worktree.branch} --no-ff -m "Merge swarm winner: ${best.worktree.slug}"`,
|
|
5072
5138
|
{ cwd: root, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
5073
5139
|
);
|
|
@@ -5126,13 +5192,14 @@ async function deriveMultipleHypotheses(goal, root, count) {
|
|
|
5126
5192
|
readFileOrEmpty(path14.join(root, "docs", "synthesis", "dead-ends.md")),
|
|
5127
5193
|
CONTEXT_LIMITS.deadEnds
|
|
5128
5194
|
);
|
|
5195
|
+
const diagnosis = truncateContext(readLatestDiagnosis(root), CONTEXT_LIMITS.synthesis);
|
|
5129
5196
|
const db = getDb(root);
|
|
5130
5197
|
const deadEnds = listAllDeadEnds(db);
|
|
5131
5198
|
const config = loadConfig(root);
|
|
5132
5199
|
let metricsOutput = "";
|
|
5133
5200
|
if (config.metrics?.command) {
|
|
5134
5201
|
try {
|
|
5135
|
-
metricsOutput = (0,
|
|
5202
|
+
metricsOutput = (0, import_node_child_process8.execSync)(config.metrics.command, {
|
|
5136
5203
|
cwd: root,
|
|
5137
5204
|
encoding: "utf-8",
|
|
5138
5205
|
timeout: 6e4,
|
|
@@ -5147,7 +5214,10 @@ async function deriveMultipleHypotheses(goal, root, count) {
|
|
|
5147
5214
|
|
|
5148
5215
|
## Goal
|
|
5149
5216
|
${goal}
|
|
5150
|
-
|
|
5217
|
+
${diagnosis ? `
|
|
5218
|
+
## Latest Diagnosis Report (PRIORITISE \u2014 deep analysis from diagnostician agent)
|
|
5219
|
+
${diagnosis}
|
|
5220
|
+
` : ""}
|
|
5151
5221
|
## Current Metrics
|
|
5152
5222
|
${metricsOutput || "(no metrics configured)"}
|
|
5153
5223
|
|
|
@@ -5167,6 +5237,8 @@ Note: [structural] dead ends are HARD CONSTRAINTS \u2014 hypotheses MUST NOT rep
|
|
|
5167
5237
|
[procedural] dead ends are process failures \u2014 the approach may still be valid if executed differently.
|
|
5168
5238
|
|
|
5169
5239
|
## Your Task
|
|
5240
|
+
DO NOT read source code or use tools. All context you need is above. Plan from the synthesis and dead-end registry.
|
|
5241
|
+
|
|
5170
5242
|
1. Assess: based on the metrics and synthesis, has the goal been met? Be specific.
|
|
5171
5243
|
2. If YES \u2014 output the JSON block below with goal_met: true.
|
|
5172
5244
|
3. If NO \u2014 generate exactly ${count} DIVERSE hypotheses for parallel testing.
|
|
@@ -5184,7 +5256,7 @@ CRITICAL: Your LAST line of output MUST be EXACTLY this format (on its own line,
|
|
|
5184
5256
|
|
|
5185
5257
|
If the goal is met:
|
|
5186
5258
|
<!-- majlis-json {"goal_met": true, "hypotheses": []} -->`
|
|
5187
|
-
}, root);
|
|
5259
|
+
}, root, { maxTurns: 2, tools: [] });
|
|
5188
5260
|
if (result.structured?.goal_met === true) return [];
|
|
5189
5261
|
if (result.structured?.hypotheses && Array.isArray(result.structured.hypotheses)) {
|
|
5190
5262
|
return result.structured.hypotheses.filter(
|
|
@@ -5207,12 +5279,12 @@ If the goal is met:
|
|
|
5207
5279
|
warn("Planner did not return structured hypotheses. Using goal as single hypothesis.");
|
|
5208
5280
|
return [goal];
|
|
5209
5281
|
}
|
|
5210
|
-
var path14,
|
|
5282
|
+
var path14, import_node_child_process8, MAX_PARALLEL, DEFAULT_PARALLEL;
|
|
5211
5283
|
var init_swarm = __esm({
|
|
5212
5284
|
"src/commands/swarm.ts"() {
|
|
5213
5285
|
"use strict";
|
|
5214
5286
|
path14 = __toESM(require("path"));
|
|
5215
|
-
|
|
5287
|
+
import_node_child_process8 = require("child_process");
|
|
5216
5288
|
init_connection();
|
|
5217
5289
|
init_queries();
|
|
5218
5290
|
init_spawn();
|
|
@@ -5251,7 +5323,7 @@ async function diagnose(args) {
|
|
|
5251
5323
|
let metricsOutput = "";
|
|
5252
5324
|
if (config.metrics?.command) {
|
|
5253
5325
|
try {
|
|
5254
|
-
metricsOutput = (0,
|
|
5326
|
+
metricsOutput = (0, import_node_child_process9.execSync)(config.metrics.command, {
|
|
5255
5327
|
cwd: root,
|
|
5256
5328
|
encoding: "utf-8",
|
|
5257
5329
|
timeout: 6e4,
|
|
@@ -5330,19 +5402,21 @@ Remember: you may write files ONLY to .majlis/scripts/. You cannot modify projec
|
|
|
5330
5402
|
if (result.truncated) {
|
|
5331
5403
|
warn("Diagnostician was truncated (hit 60 turn limit).");
|
|
5332
5404
|
}
|
|
5405
|
+
autoCommit(root, `diagnosis: ${focus || "general"}`);
|
|
5333
5406
|
success("Diagnosis complete.");
|
|
5334
5407
|
}
|
|
5335
|
-
var fs14, path15,
|
|
5408
|
+
var fs14, path15, import_node_child_process9;
|
|
5336
5409
|
var init_diagnose = __esm({
|
|
5337
5410
|
"src/commands/diagnose.ts"() {
|
|
5338
5411
|
"use strict";
|
|
5339
5412
|
fs14 = __toESM(require("fs"));
|
|
5340
5413
|
path15 = __toESM(require("path"));
|
|
5341
|
-
|
|
5414
|
+
import_node_child_process9 = require("child_process");
|
|
5342
5415
|
init_connection();
|
|
5343
5416
|
init_queries();
|
|
5344
5417
|
init_spawn();
|
|
5345
5418
|
init_config();
|
|
5419
|
+
init_git();
|
|
5346
5420
|
init_format();
|
|
5347
5421
|
}
|
|
5348
5422
|
});
|