harnessed 4.1.1 → 4.1.2

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 CHANGED
@@ -1271,7 +1271,7 @@ var init_auto_install = __esm({
1271
1271
 
1272
1272
  // package.json
1273
1273
  var package_default = {
1274
- version: "4.1.1"};
1274
+ version: "4.1.2"};
1275
1275
 
1276
1276
  // src/manifest/errors.ts
1277
1277
  function instancePathToKeyPath(instancePath) {
@@ -2572,23 +2572,18 @@ async function resolveJudgmentGate(gateRef, context, packageRoot) {
2572
2572
  }
2573
2573
  return evalGate(expr, context);
2574
2574
  }
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
2575
 
2584
- // src/cli/gates.ts
2585
- var VALID_MASTERS = /* @__PURE__ */ new Set(["auto", "discuss", "plan", "task", "verify"]);
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) {
2576
+ // src/cli/lib/gateContext.ts
2577
+ function buildDefaultGateContext(task, stage) {
2589
2578
  return {
2590
2579
  task,
2591
2580
  user_understanding_unclear: false,
2581
+ // v4.1.2 — parallelism-gate.agent-teams-upgrade team-routing facts (default off).
2582
+ teammate_send_message_needed: false,
2583
+ subagent_context_overflow: false,
2584
+ shared_task_list: false,
2585
+ opposing_hypothesis_debate: false,
2586
+ fullstack_three_way: false,
2592
2587
  phase: {
2593
2588
  stage,
2594
2589
  is_critical_module: true,
@@ -2627,6 +2622,30 @@ function defaultContext(task, stage) {
2627
2622
  }
2628
2623
  };
2629
2624
  }
2625
+ function mergeGateContext(base, extra) {
2626
+ const merged = { ...base };
2627
+ for (const [k, v] of Object.entries(extra)) {
2628
+ if ((k === "phase" || k === "subtask") && v && typeof v === "object" && !Array.isArray(v)) {
2629
+ merged[k] = { ...base[k], ...v };
2630
+ } else {
2631
+ merged[k] = v;
2632
+ }
2633
+ }
2634
+ return merged;
2635
+ }
2636
+ function getPackageRoot() {
2637
+ const thisFile = fileURLToPath(import.meta.url);
2638
+ const thisDir = dirname(thisFile);
2639
+ if (thisDir.endsWith("dist") || thisDir.replace(/\\/g, "/").endsWith("/dist")) {
2640
+ return resolve(thisDir, "..");
2641
+ }
2642
+ return resolve(thisDir, "..", "..", "..");
2643
+ }
2644
+
2645
+ // src/cli/gates.ts
2646
+ var VALID_MASTERS = /* @__PURE__ */ new Set(["auto", "discuss", "plan", "task", "verify"]);
2647
+ var STAGE_MASTERS = /* @__PURE__ */ new Set(["discuss", "plan", "task", "verify"]);
2648
+ var PARALLELISM_GATE = "judgments.parallelism-gate.agent-teams-upgrade.fires";
2630
2649
  function resolveMasterYamlPath(master, packageRoot) {
2631
2650
  return master === "auto" ? resolve(packageRoot, "workflows", "auto", "workflow.yaml") : resolve(packageRoot, "workflows", master, "auto", "workflow.yaml");
2632
2651
  }
@@ -2670,7 +2689,7 @@ function registerGates(program2) {
2670
2689
  const clauses = delegates;
2671
2690
  const task = typeof raw.task === "string" ? raw.task : "";
2672
2691
  const stage = master;
2673
- const ctx = defaultContext(task, stage);
2692
+ let ctx = buildDefaultGateContext(task, stage);
2674
2693
  if (typeof raw.context === "string" && raw.context.length > 0) {
2675
2694
  let extra;
2676
2695
  try {
@@ -2680,15 +2699,14 @@ function registerGates(program2) {
2680
2699
  process.exit(1);
2681
2700
  return;
2682
2701
  }
2683
- if (extra && typeof extra === "object") {
2684
- Object.assign(ctx, extra);
2702
+ if (extra && typeof extra === "object" && !Array.isArray(extra)) {
2703
+ ctx = mergeGateContext(ctx, extra);
2685
2704
  }
2686
2705
  }
2687
2706
  const skipSubs = new Set(
2688
2707
  typeof raw.skipSub === "string" && raw.skipSub.length > 0 ? raw.skipSub.split(",").map((s) => s.trim()).filter((s) => s.length > 0) : []
2689
2708
  );
2690
2709
  ctx.skip_subs = [...skipSubs];
2691
- ctx.task = task;
2692
2710
  const fire = [];
2693
2711
  const skip = [];
2694
2712
  for (const clause of clauses) {
@@ -2700,13 +2718,13 @@ function registerGates(program2) {
2700
2718
  continue;
2701
2719
  }
2702
2720
  if (!clause.gate) {
2703
- fire.push(fireEntry(clause));
2721
+ fire.push(fireEntry(clause, master));
2704
2722
  continue;
2705
2723
  }
2706
2724
  try {
2707
2725
  const passes = await resolveJudgmentGate(clause.gate, ctx, packageRoot);
2708
2726
  if (passes) {
2709
- fire.push(fireEntry(clause));
2727
+ fire.push(fireEntry(clause, master));
2710
2728
  } else {
2711
2729
  skip.push({ sub: clause.sub, reason: `gate ${clause.gate} = false` });
2712
2730
  }
@@ -2714,7 +2732,7 @@ function registerGates(program2) {
2714
2732
  console.warn(
2715
2733
  `\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
2734
  );
2717
- fire.push(fireEntry(clause));
2735
+ fire.push(fireEntry(clause, master));
2718
2736
  }
2719
2737
  }
2720
2738
  let parallelism = { escalate_to_teams: false, reason: null };
@@ -2729,14 +2747,14 @@ function registerGates(program2) {
2729
2747
  process.exit(0);
2730
2748
  });
2731
2749
  }
2732
- function fireEntry(clause) {
2733
- const entry = { sub: clause.sub };
2750
+ function fireEntry(clause, master) {
2751
+ const isMaster = STAGE_MASTERS.has(clause.sub);
2752
+ const sub = master !== "auto" && !isMaster ? `${master}-${clause.sub}` : clause.sub;
2753
+ const entry = { sub };
2734
2754
  if (clause.order !== void 0) entry.order = clause.order;
2735
2755
  if (clause.mode !== void 0) entry.mode = clause.mode;
2736
2756
  if (clause.gate !== void 0) entry.gate = clause.gate;
2737
- if (STAGE_MASTERS.has(clause.sub)) {
2738
- entry.is_master = true;
2739
- }
2757
+ if (isMaster) entry.is_master = true;
2740
2758
  return entry;
2741
2759
  }
2742
2760
  var DURATION_RE = /^(\d+)([dhmw])$/;
@@ -4537,7 +4555,7 @@ function nameToYamlHintPath(name) {
4537
4555
  }
4538
4556
  return `${name}/workflow.yaml`;
4539
4557
  }
4540
- var HARNESSED_MARKER_RX = /<!--\s*harnessed-generated:v3\.4\.\d+\s*-->/;
4558
+ var HARNESSED_MARKER_RX = /<!--\s*harnessed-generated:v\d+\.\d+\.\d+\s*-->/;
4541
4559
  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
4560
  var V3_4_3_SIGNATURE_MASTER_RX = /\*\*Preferred path\*\*[\s\S]*dispatch to the per-sub-workflow/;
4543
4561
  function shouldOverwriteFile(content) {
@@ -5801,63 +5819,7 @@ function registerRun(program2) {
5801
5819
  }
5802
5820
  const stage = name.includes("-") ? name.split("-")[0] ?? "" : name;
5803
5821
  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
- },
5822
+ ...buildDefaultGateContext(task, stage),
5861
5823
  ...raw.model ? { modelOverride: raw.model } : {},
5862
5824
  ...raw.maxIterations ? { maxIterations: raw.maxIterations } : {},
5863
5825
  ...raw.staged ? { staged: true } : {},
@@ -5989,14 +5951,17 @@ var LANG_NAMES = {
5989
5951
  "zh-Hant": "\u7E41\u9AD4\u4E2D\u6587 (Traditional Chinese)",
5990
5952
  "zh-TW": "\u7E41\u9AD4\u4E2D\u6587 (Traditional Chinese)"
5991
5953
  };
5954
+ async function loadSubArrayField(sub, packageRoot, field) {
5955
+ const subYaml = await resolveWorkflowYaml(sub, resolve(packageRoot, "workflows"));
5956
+ if (!subYaml) return [];
5957
+ const wf = parse(await readFile(subYaml, "utf8"));
5958
+ const v = wf?.[field];
5959
+ return Array.isArray(v) ? v : [];
5960
+ }
5992
5961
  async function buildToolsSection(sub, packageRoot) {
5993
5962
  try {
5994
5963
  const workflowsDir = resolve(packageRoot, "workflows");
5995
- const subYaml = await resolveWorkflowYaml(sub, workflowsDir);
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 : [];
5964
+ const tools = await loadSubArrayField(sub, packageRoot, "tools_available");
6000
5965
  if (tools.length === 0) return "";
6001
5966
  const capRaw = await readFile(resolve(workflowsDir, "capabilities.yaml"), "utf8");
6002
5967
  const capDoc = parse(capRaw);
@@ -6020,11 +5985,7 @@ ${lines.join("\n")}
6020
5985
  async function buildDisciplinesSection(sub, packageRoot) {
6021
5986
  try {
6022
5987
  const workflowsDir = resolve(packageRoot, "workflows");
6023
- const subYaml = await resolveWorkflowYaml(sub, workflowsDir);
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 : [];
5988
+ const applied = await loadSubArrayField(sub, packageRoot, "disciplines_applied");
6028
5989
  const names = applied.filter((d) => d !== "language");
6029
5990
  if (names.length === 0) return "";
6030
5991
  const blocks = [];
@@ -6097,7 +6058,7 @@ function registerPrompt(program2) {
6097
6058
  const packageRoot = getPackageRoot();
6098
6059
  const workflowsDir = resolve(packageRoot, "workflows");
6099
6060
  const rolePrompts = await loadRolePrompts(workflowsDir);
6100
- const def = buildAgentDef(sub, rolePrompts, void 0, void 0, void 0);
6061
+ const def = buildAgentDef(sub, rolePrompts);
6101
6062
  const body = def.prompt;
6102
6063
  const taskSection = typeof raw.task === "string" && raw.task.length > 0 ? `## Task
6103
6064
  ${raw.task}
@@ -6121,7 +6082,6 @@ ${toolsSection}${disciplinesSection}${PROTOCOLS}${buildLanguageSection()}`;
6121
6082
  })
6122
6083
  );
6123
6084
  process.exit(0);
6124
- return;
6125
6085
  }
6126
6086
  console.log(fullPrompt);
6127
6087
  process.exit(0);