harnessed 4.1.1 → 4.1.3
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.mjs +104 -112
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -186,6 +186,20 @@ var init_schemaVersion = __esm({
|
|
|
186
186
|
]);
|
|
187
187
|
}
|
|
188
188
|
});
|
|
189
|
+
async function writeFileAtomic(path, data) {
|
|
190
|
+
const tmp = `${path}.tmp`;
|
|
191
|
+
await writeFile(tmp, data, "utf8");
|
|
192
|
+
await rename(tmp, path);
|
|
193
|
+
}
|
|
194
|
+
function writeFileSyncAtomic(path, data) {
|
|
195
|
+
const tmp = `${path}.tmp`;
|
|
196
|
+
writeFileSync(tmp, data, "utf8");
|
|
197
|
+
renameSync(tmp, path);
|
|
198
|
+
}
|
|
199
|
+
var init_atomicWrite = __esm({
|
|
200
|
+
"src/checkpoint/atomicWrite.ts"() {
|
|
201
|
+
}
|
|
202
|
+
});
|
|
189
203
|
var CheckpointStatus, CheckpointV1;
|
|
190
204
|
var init_checkpoint_v1 = __esm({
|
|
191
205
|
"src/checkpoint/schema/checkpoint.v1.ts"() {
|
|
@@ -305,7 +319,7 @@ async function writeCurrentWorkflow(s) {
|
|
|
305
319
|
const path = statePath();
|
|
306
320
|
await mkdir(dirname(path), { recursive: true });
|
|
307
321
|
await withLock(async () => {
|
|
308
|
-
await
|
|
322
|
+
await writeFileAtomic(path, JSON.stringify(s, null, 2));
|
|
309
323
|
});
|
|
310
324
|
}
|
|
311
325
|
async function activate(phase, checkpointPath = null) {
|
|
@@ -332,6 +346,7 @@ var init_state = __esm({
|
|
|
332
346
|
"src/checkpoint/state.ts"() {
|
|
333
347
|
init_harnessedRoot();
|
|
334
348
|
init_schemaVersion();
|
|
349
|
+
init_atomicWrite();
|
|
335
350
|
init_schema();
|
|
336
351
|
WorkflowStateError = class extends Error {
|
|
337
352
|
constructor(message) {
|
|
@@ -375,13 +390,14 @@ function writeCheckpoint(c, customPath) {
|
|
|
375
390
|
const enforced = enforceBudget(c);
|
|
376
391
|
const path = join(harnessedSubdir("checkpoints"), `${enforced.phase}.json`);
|
|
377
392
|
mkdirSync(dirname(path), { recursive: true });
|
|
378
|
-
|
|
393
|
+
writeFileSyncAtomic(path, JSON.stringify(enforced, null, 2));
|
|
379
394
|
return path;
|
|
380
395
|
}
|
|
381
396
|
var BUDGET_TOKEN, CheckpointTooLargeError, CheckpointWriteError;
|
|
382
397
|
var init_template = __esm({
|
|
383
398
|
"src/checkpoint/template.ts"() {
|
|
384
399
|
init_harnessedRoot();
|
|
400
|
+
init_atomicWrite();
|
|
385
401
|
init_schema();
|
|
386
402
|
BUDGET_TOKEN = 1e3;
|
|
387
403
|
CheckpointTooLargeError = class extends Error {
|
|
@@ -1271,7 +1287,7 @@ var init_auto_install = __esm({
|
|
|
1271
1287
|
|
|
1272
1288
|
// package.json
|
|
1273
1289
|
var package_default = {
|
|
1274
|
-
version: "4.1.
|
|
1290
|
+
version: "4.1.3"};
|
|
1275
1291
|
|
|
1276
1292
|
// src/manifest/errors.ts
|
|
1277
1293
|
function instancePathToKeyPath(instancePath) {
|
|
@@ -2572,23 +2588,18 @@ async function resolveJudgmentGate(gateRef, context, packageRoot) {
|
|
|
2572
2588
|
}
|
|
2573
2589
|
return evalGate(expr, context);
|
|
2574
2590
|
}
|
|
2575
|
-
function getPackageRoot() {
|
|
2576
|
-
const thisFile = fileURLToPath(import.meta.url);
|
|
2577
|
-
const thisDir = dirname(thisFile);
|
|
2578
|
-
if (thisDir.endsWith("dist") || thisDir.replace(/\\/g, "/").endsWith("/dist")) {
|
|
2579
|
-
return resolve(thisDir, "..");
|
|
2580
|
-
}
|
|
2581
|
-
return resolve(thisDir, "..", "..", "..");
|
|
2582
|
-
}
|
|
2583
2591
|
|
|
2584
|
-
// src/cli/
|
|
2585
|
-
|
|
2586
|
-
var STAGE_MASTERS = /* @__PURE__ */ new Set(["discuss", "plan", "task", "verify"]);
|
|
2587
|
-
var PARALLELISM_GATE = "judgments.parallelism-gate.agent-teams-upgrade.fires";
|
|
2588
|
-
function defaultContext(task, stage) {
|
|
2592
|
+
// src/cli/lib/gateContext.ts
|
|
2593
|
+
function buildDefaultGateContext(task, stage) {
|
|
2589
2594
|
return {
|
|
2590
2595
|
task,
|
|
2591
2596
|
user_understanding_unclear: false,
|
|
2597
|
+
// v4.1.2 — parallelism-gate.agent-teams-upgrade team-routing facts (default off).
|
|
2598
|
+
teammate_send_message_needed: false,
|
|
2599
|
+
subagent_context_overflow: false,
|
|
2600
|
+
shared_task_list: false,
|
|
2601
|
+
opposing_hypothesis_debate: false,
|
|
2602
|
+
fullstack_three_way: false,
|
|
2592
2603
|
phase: {
|
|
2593
2604
|
stage,
|
|
2594
2605
|
is_critical_module: true,
|
|
@@ -2627,6 +2638,30 @@ function defaultContext(task, stage) {
|
|
|
2627
2638
|
}
|
|
2628
2639
|
};
|
|
2629
2640
|
}
|
|
2641
|
+
function mergeGateContext(base, extra) {
|
|
2642
|
+
const merged = { ...base };
|
|
2643
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
2644
|
+
if ((k === "phase" || k === "subtask") && v && typeof v === "object" && !Array.isArray(v)) {
|
|
2645
|
+
merged[k] = { ...base[k], ...v };
|
|
2646
|
+
} else {
|
|
2647
|
+
merged[k] = v;
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
return merged;
|
|
2651
|
+
}
|
|
2652
|
+
function getPackageRoot() {
|
|
2653
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
2654
|
+
const thisDir = dirname(thisFile);
|
|
2655
|
+
if (thisDir.endsWith("dist") || thisDir.replace(/\\/g, "/").endsWith("/dist")) {
|
|
2656
|
+
return resolve(thisDir, "..");
|
|
2657
|
+
}
|
|
2658
|
+
return resolve(thisDir, "..", "..", "..");
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
// src/cli/gates.ts
|
|
2662
|
+
var VALID_MASTERS = /* @__PURE__ */ new Set(["auto", "discuss", "plan", "task", "verify"]);
|
|
2663
|
+
var STAGE_MASTERS = /* @__PURE__ */ new Set(["discuss", "plan", "task", "verify"]);
|
|
2664
|
+
var PARALLELISM_GATE = "judgments.parallelism-gate.agent-teams-upgrade.fires";
|
|
2630
2665
|
function resolveMasterYamlPath(master, packageRoot) {
|
|
2631
2666
|
return master === "auto" ? resolve(packageRoot, "workflows", "auto", "workflow.yaml") : resolve(packageRoot, "workflows", master, "auto", "workflow.yaml");
|
|
2632
2667
|
}
|
|
@@ -2670,7 +2705,7 @@ function registerGates(program2) {
|
|
|
2670
2705
|
const clauses = delegates;
|
|
2671
2706
|
const task = typeof raw.task === "string" ? raw.task : "";
|
|
2672
2707
|
const stage = master;
|
|
2673
|
-
|
|
2708
|
+
let ctx = buildDefaultGateContext(task, stage);
|
|
2674
2709
|
if (typeof raw.context === "string" && raw.context.length > 0) {
|
|
2675
2710
|
let extra;
|
|
2676
2711
|
try {
|
|
@@ -2680,15 +2715,14 @@ function registerGates(program2) {
|
|
|
2680
2715
|
process.exit(1);
|
|
2681
2716
|
return;
|
|
2682
2717
|
}
|
|
2683
|
-
if (extra && typeof extra === "object") {
|
|
2684
|
-
|
|
2718
|
+
if (extra && typeof extra === "object" && !Array.isArray(extra)) {
|
|
2719
|
+
ctx = mergeGateContext(ctx, extra);
|
|
2685
2720
|
}
|
|
2686
2721
|
}
|
|
2687
2722
|
const skipSubs = new Set(
|
|
2688
2723
|
typeof raw.skipSub === "string" && raw.skipSub.length > 0 ? raw.skipSub.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : []
|
|
2689
2724
|
);
|
|
2690
2725
|
ctx.skip_subs = [...skipSubs];
|
|
2691
|
-
ctx.task = task;
|
|
2692
2726
|
const fire = [];
|
|
2693
2727
|
const skip = [];
|
|
2694
2728
|
for (const clause of clauses) {
|
|
@@ -2700,13 +2734,13 @@ function registerGates(program2) {
|
|
|
2700
2734
|
continue;
|
|
2701
2735
|
}
|
|
2702
2736
|
if (!clause.gate) {
|
|
2703
|
-
fire.push(fireEntry(clause));
|
|
2737
|
+
fire.push(fireEntry(clause, master));
|
|
2704
2738
|
continue;
|
|
2705
2739
|
}
|
|
2706
2740
|
try {
|
|
2707
2741
|
const passes = await resolveJudgmentGate(clause.gate, ctx, packageRoot);
|
|
2708
2742
|
if (passes) {
|
|
2709
|
-
fire.push(fireEntry(clause));
|
|
2743
|
+
fire.push(fireEntry(clause, master));
|
|
2710
2744
|
} else {
|
|
2711
2745
|
skip.push({ sub: clause.sub, reason: `gate ${clause.gate} = false` });
|
|
2712
2746
|
}
|
|
@@ -2714,7 +2748,7 @@ function registerGates(program2) {
|
|
|
2714
2748
|
console.warn(
|
|
2715
2749
|
`\u26A0\uFE0F master ${master} sub ${clause.sub} gate ${clause.gate} eval failed (${e.message}); firing sub as if gate=true (ADR 0029 fail-soft).`
|
|
2716
2750
|
);
|
|
2717
|
-
fire.push(fireEntry(clause));
|
|
2751
|
+
fire.push(fireEntry(clause, master));
|
|
2718
2752
|
}
|
|
2719
2753
|
}
|
|
2720
2754
|
let parallelism = { escalate_to_teams: false, reason: null };
|
|
@@ -2729,14 +2763,14 @@ function registerGates(program2) {
|
|
|
2729
2763
|
process.exit(0);
|
|
2730
2764
|
});
|
|
2731
2765
|
}
|
|
2732
|
-
function fireEntry(clause) {
|
|
2733
|
-
const
|
|
2766
|
+
function fireEntry(clause, master) {
|
|
2767
|
+
const isMaster = STAGE_MASTERS.has(clause.sub);
|
|
2768
|
+
const sub = master !== "auto" && !isMaster ? `${master}-${clause.sub}` : clause.sub;
|
|
2769
|
+
const entry = { sub };
|
|
2734
2770
|
if (clause.order !== void 0) entry.order = clause.order;
|
|
2735
2771
|
if (clause.mode !== void 0) entry.mode = clause.mode;
|
|
2736
2772
|
if (clause.gate !== void 0) entry.gate = clause.gate;
|
|
2737
|
-
if (
|
|
2738
|
-
entry.is_master = true;
|
|
2739
|
-
}
|
|
2773
|
+
if (isMaster) entry.is_master = true;
|
|
2740
2774
|
return entry;
|
|
2741
2775
|
}
|
|
2742
2776
|
var DURATION_RE = /^(\d+)([dhmw])$/;
|
|
@@ -2790,7 +2824,7 @@ ${t("gc.invalid_duration.fix")}`
|
|
|
2790
2824
|
return;
|
|
2791
2825
|
}
|
|
2792
2826
|
const cutoff = Date.now() - olderMs;
|
|
2793
|
-
const kept = new Set(dirs.slice(-keepLast));
|
|
2827
|
+
const kept = new Set(keepLast > 0 ? dirs.slice(-keepLast) : []);
|
|
2794
2828
|
const candidates = [];
|
|
2795
2829
|
for (const ts of dirs) {
|
|
2796
2830
|
if (kept.has(ts)) continue;
|
|
@@ -4537,7 +4571,7 @@ function nameToYamlHintPath(name) {
|
|
|
4537
4571
|
}
|
|
4538
4572
|
return `${name}/workflow.yaml`;
|
|
4539
4573
|
}
|
|
4540
|
-
var HARNESSED_MARKER_RX = /<!--\s*harnessed-generated:
|
|
4574
|
+
var HARNESSED_MARKER_RX = /<!--\s*harnessed-generated:v\d+\.\d+\.\d+\s*-->/;
|
|
4541
4575
|
var V3_4_3_SIGNATURE_SUB_RX = /\*\*Preferred path\*\*[\s\S]*use the SlashCommand tool[\s\S]*\*\*Fallback path\*\*[\s\S]*use the Task tool to spawn/;
|
|
4542
4576
|
var V3_4_3_SIGNATURE_MASTER_RX = /\*\*Preferred path\*\*[\s\S]*dispatch to the per-sub-workflow/;
|
|
4543
4577
|
function shouldOverwriteFile(content) {
|
|
@@ -5801,63 +5835,7 @@ function registerRun(program2) {
|
|
|
5801
5835
|
}
|
|
5802
5836
|
const stage = name.includes("-") ? name.split("-")[0] ?? "" : name;
|
|
5803
5837
|
const gateContext = {
|
|
5804
|
-
task,
|
|
5805
|
-
// v3.9.24 — top-level fact set by runAutoPreFlight() when /auto super-master
|
|
5806
|
-
// Phase 0.5 understanding-check prompt fires. CLI path skips preflight
|
|
5807
|
-
// (no readline hooks), so default to false → research sub skips by default.
|
|
5808
|
-
user_understanding_unclear: false,
|
|
5809
|
-
phase: {
|
|
5810
|
-
stage,
|
|
5811
|
-
// verify-stage gates
|
|
5812
|
-
is_critical_module: true,
|
|
5813
|
-
// verify-paranoid fires
|
|
5814
|
-
is_final_step: true,
|
|
5815
|
-
// verify-simplify fires
|
|
5816
|
-
is_major_release: false,
|
|
5817
|
-
// verify-multispec only for major
|
|
5818
|
-
has_auth_or_secrets: false,
|
|
5819
|
-
has_design_changes: false,
|
|
5820
|
-
has_ui_changes: false,
|
|
5821
|
-
requires_creative_polish: false,
|
|
5822
|
-
// plan-stage gates
|
|
5823
|
-
is_complex_architecture: true,
|
|
5824
|
-
// plan-architecture fires
|
|
5825
|
-
// discuss-stage gates
|
|
5826
|
-
has_cross_phase_data_flow: true,
|
|
5827
|
-
// discuss-phase fires
|
|
5828
|
-
open_decisions: 2,
|
|
5829
|
-
// ≥2 fires phase-gate
|
|
5830
|
-
scope_days: 2,
|
|
5831
|
-
// >1 day fires phase-gate
|
|
5832
|
-
scope_locked_in_history: false,
|
|
5833
|
-
single_task: false,
|
|
5834
|
-
type: "general"
|
|
5835
|
-
},
|
|
5836
|
-
subtask: {
|
|
5837
|
-
// subtask brainstorming gate
|
|
5838
|
-
approaches: 2,
|
|
5839
|
-
// ≥2 fires
|
|
5840
|
-
core_algorithm: true,
|
|
5841
|
-
has_api_contract: true,
|
|
5842
|
-
error_cost: "high",
|
|
5843
|
-
lines: 50,
|
|
5844
|
-
// ≥20 → no skip
|
|
5845
|
-
type: "general",
|
|
5846
|
-
// not crud/standard_lib_call → no skip
|
|
5847
|
-
// tdd gate
|
|
5848
|
-
is_core_business_logic: true,
|
|
5849
|
-
is_algorithm: true,
|
|
5850
|
-
is_data_processing: true,
|
|
5851
|
-
regression_risk: "high",
|
|
5852
|
-
reliability_required: true,
|
|
5853
|
-
// misc
|
|
5854
|
-
communication_needed: false,
|
|
5855
|
-
needs_lib_docs: false,
|
|
5856
|
-
needs_web_search: false,
|
|
5857
|
-
parallel_count: 1,
|
|
5858
|
-
search_type: "general",
|
|
5859
|
-
test_type: "general"
|
|
5860
|
-
},
|
|
5838
|
+
...buildDefaultGateContext(task, stage),
|
|
5861
5839
|
...raw.model ? { modelOverride: raw.model } : {},
|
|
5862
5840
|
...raw.maxIterations ? { maxIterations: raw.maxIterations } : {},
|
|
5863
5841
|
...raw.staged ? { staged: true } : {},
|
|
@@ -5989,14 +5967,17 @@ var LANG_NAMES = {
|
|
|
5989
5967
|
"zh-Hant": "\u7E41\u9AD4\u4E2D\u6587 (Traditional Chinese)",
|
|
5990
5968
|
"zh-TW": "\u7E41\u9AD4\u4E2D\u6587 (Traditional Chinese)"
|
|
5991
5969
|
};
|
|
5970
|
+
async function loadSubArrayField(sub, packageRoot, field) {
|
|
5971
|
+
const subYaml = await resolveWorkflowYaml(sub, resolve(packageRoot, "workflows"));
|
|
5972
|
+
if (!subYaml) return [];
|
|
5973
|
+
const wf = parse(await readFile(subYaml, "utf8"));
|
|
5974
|
+
const v = wf?.[field];
|
|
5975
|
+
return Array.isArray(v) ? v : [];
|
|
5976
|
+
}
|
|
5992
5977
|
async function buildToolsSection(sub, packageRoot) {
|
|
5993
5978
|
try {
|
|
5994
5979
|
const workflowsDir = resolve(packageRoot, "workflows");
|
|
5995
|
-
const
|
|
5996
|
-
if (!subYaml) return "";
|
|
5997
|
-
const wfRaw = await readFile(subYaml, "utf8");
|
|
5998
|
-
const wf = parse(wfRaw);
|
|
5999
|
-
const tools = Array.isArray(wf?.tools_available) ? wf.tools_available : [];
|
|
5980
|
+
const tools = await loadSubArrayField(sub, packageRoot, "tools_available");
|
|
6000
5981
|
if (tools.length === 0) return "";
|
|
6001
5982
|
const capRaw = await readFile(resolve(workflowsDir, "capabilities.yaml"), "utf8");
|
|
6002
5983
|
const capDoc = parse(capRaw);
|
|
@@ -6020,11 +6001,7 @@ ${lines.join("\n")}
|
|
|
6020
6001
|
async function buildDisciplinesSection(sub, packageRoot) {
|
|
6021
6002
|
try {
|
|
6022
6003
|
const workflowsDir = resolve(packageRoot, "workflows");
|
|
6023
|
-
const
|
|
6024
|
-
if (!subYaml) return "";
|
|
6025
|
-
const wfRaw = await readFile(subYaml, "utf8");
|
|
6026
|
-
const wf = parse(wfRaw);
|
|
6027
|
-
const applied = Array.isArray(wf?.disciplines_applied) ? wf.disciplines_applied : [];
|
|
6004
|
+
const applied = await loadSubArrayField(sub, packageRoot, "disciplines_applied");
|
|
6028
6005
|
const names = applied.filter((d) => d !== "language");
|
|
6029
6006
|
if (names.length === 0) return "";
|
|
6030
6007
|
const blocks = [];
|
|
@@ -6097,7 +6074,7 @@ function registerPrompt(program2) {
|
|
|
6097
6074
|
const packageRoot = getPackageRoot();
|
|
6098
6075
|
const workflowsDir = resolve(packageRoot, "workflows");
|
|
6099
6076
|
const rolePrompts = await loadRolePrompts(workflowsDir);
|
|
6100
|
-
const def = buildAgentDef(sub, rolePrompts
|
|
6077
|
+
const def = buildAgentDef(sub, rolePrompts);
|
|
6101
6078
|
const body = def.prompt;
|
|
6102
6079
|
const taskSection = typeof raw.task === "string" && raw.task.length > 0 ? `## Task
|
|
6103
6080
|
${raw.task}
|
|
@@ -6121,7 +6098,6 @@ ${toolsSection}${disciplinesSection}${PROTOCOLS}${buildLanguageSection()}`;
|
|
|
6121
6098
|
})
|
|
6122
6099
|
);
|
|
6123
6100
|
process.exit(0);
|
|
6124
|
-
return;
|
|
6125
6101
|
}
|
|
6126
6102
|
console.log(fullPrompt);
|
|
6127
6103
|
process.exit(0);
|
|
@@ -6216,21 +6192,21 @@ ${t("rollback.metadata_unreadable.fix")}`
|
|
|
6216
6192
|
process.exit(1);
|
|
6217
6193
|
return;
|
|
6218
6194
|
}
|
|
6219
|
-
|
|
6195
|
+
const ordered = [...meta.files].reverse();
|
|
6196
|
+
const planned = [];
|
|
6197
|
+
for (const entry of ordered) {
|
|
6220
6198
|
if (entry.backup === "") {
|
|
6221
|
-
|
|
6222
|
-
await unlink(entry.target);
|
|
6223
|
-
} catch (err2) {
|
|
6224
|
-
const code = err2.code;
|
|
6225
|
-
if (code !== "ENOENT") {
|
|
6226
|
-
console.error(`error: cannot unlink ${entry.target}: ${err2.message}`);
|
|
6227
|
-
process.exit(1);
|
|
6228
|
-
return;
|
|
6229
|
-
}
|
|
6230
|
-
}
|
|
6199
|
+
planned.push({ target: entry.target, action: "unlink" });
|
|
6231
6200
|
continue;
|
|
6232
6201
|
}
|
|
6233
|
-
|
|
6202
|
+
let buf;
|
|
6203
|
+
try {
|
|
6204
|
+
buf = await readFile(entry.backup);
|
|
6205
|
+
} catch (err2) {
|
|
6206
|
+
console.error(`error: cannot read backup ${entry.backup}: ${err2.message}`);
|
|
6207
|
+
process.exit(1);
|
|
6208
|
+
return;
|
|
6209
|
+
}
|
|
6234
6210
|
const sha1 = createHash("sha1").update(buf).digest("hex");
|
|
6235
6211
|
if (sha1 !== entry.sha1) {
|
|
6236
6212
|
console.error(
|
|
@@ -6243,7 +6219,23 @@ ${t("rollback.metadata_unreadable.fix")}`
|
|
|
6243
6219
|
process.exit(1);
|
|
6244
6220
|
return;
|
|
6245
6221
|
}
|
|
6246
|
-
|
|
6222
|
+
planned.push({ target: entry.target, action: "write", data: normalizeEol(buf, entry.eol) });
|
|
6223
|
+
}
|
|
6224
|
+
for (const op of planned) {
|
|
6225
|
+
if (op.action === "unlink") {
|
|
6226
|
+
try {
|
|
6227
|
+
await unlink(op.target);
|
|
6228
|
+
} catch (err2) {
|
|
6229
|
+
const code = err2.code;
|
|
6230
|
+
if (code !== "ENOENT") {
|
|
6231
|
+
console.error(`error: cannot unlink ${op.target}: ${err2.message}`);
|
|
6232
|
+
process.exit(1);
|
|
6233
|
+
return;
|
|
6234
|
+
}
|
|
6235
|
+
}
|
|
6236
|
+
} else {
|
|
6237
|
+
await writeFile(op.target, op.data);
|
|
6238
|
+
}
|
|
6247
6239
|
}
|
|
6248
6240
|
console.log(t("rollback.restored", { count: meta.files.length, timestamp }));
|
|
6249
6241
|
});
|