@gethmy/agent 1.14.3 → 1.14.4

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 CHANGED
@@ -7088,6 +7088,9 @@ function buildStagePreamble(stage) {
7088
7088
  }
7089
7089
  }
7090
7090
  lines.push("Do only this stage's work. When the stage's handoff is met, end your session — advancement to the next stage is handled by the board.");
7091
+ if (normalizeGateSpec(stage.gate)?.kind === "review_passed") {
7092
+ lines.push("", "**This stage's gate is `review_passed` — your deliverable is a review verdict, not a prose handoff.** Do NOT end the session until you have actually reviewed the change and emitted EXACTLY one JSON block as the LAST thing you output (nothing after it):", "```json", REVIEW_VERDICT_SCHEMA, "```", "Decision rules:", REVIEW_DECISION_RULES, "The board reads this verdict to decide advancement: `approved` advances the card, `rejected` sends it back. A missing or unparseable verdict blocks the card. Do NOT modify any code — this is a read-only review.");
7093
+ }
7091
7094
  return lines.filter(Boolean).join(`
7092
7095
  `);
7093
7096
  }
@@ -7132,6 +7135,7 @@ class Worker {
7132
7135
  lastDrainedSeq = 0;
7133
7136
  runCostCents = 0;
7134
7137
  runTurns = 0;
7138
+ lastRunText = "";
7135
7139
  constructor(id, config, client, agentId, onDone, workspaceId, projectId, stateStore, onCardCompleted, onApiError) {
7136
7140
  this.config = config;
7137
7141
  this.client = client;
@@ -7200,6 +7204,7 @@ class Worker {
7200
7204
  this.completionStarted = false;
7201
7205
  this.runCostCents = 0;
7202
7206
  this.runTurns = 0;
7207
+ this.lastRunText = "";
7203
7208
  this.cliSessionId = null;
7204
7209
  this.lastDrainedSeq = 0;
7205
7210
  this.cardId = card.id;
@@ -7652,6 +7657,10 @@ class Worker {
7652
7657
  log.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
7653
7658
  return null;
7654
7659
  }
7660
+ const review = gate.kind === "review_passed" ? parseReviewOutput(this.lastRunText) : undefined;
7661
+ if (review) {
7662
+ log.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
7663
+ }
7655
7664
  const registry = buildGateCollectorRegistry({
7656
7665
  build: {
7657
7666
  worktreePath,
@@ -7662,7 +7671,8 @@ class Worker {
7662
7671
  worktreePath,
7663
7672
  artifactType: stage.artifact_type
7664
7673
  },
7665
- checklist: { subtasks, cardDone: card.done ?? false }
7674
+ checklist: { subtasks, cardDone: card.done ?? false },
7675
+ ...review ? { review } : {}
7666
7676
  });
7667
7677
  const context = {
7668
7678
  cardId: card.id,
@@ -8000,6 +8010,9 @@ class Worker {
8000
8010
  });
8001
8011
  }
8002
8012
  }
8013
+ parser.on("text", (content) => {
8014
+ this.lastRunText += content;
8015
+ });
8003
8016
  parser.on("parse_error", (msg) => {
8004
8017
  log.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
8005
8018
  runLog?.stream.write(`
@@ -8093,6 +8106,10 @@ class Worker {
8093
8106
  try {
8094
8107
  for await (const ev of stream) {
8095
8108
  this.progressTracker?.ingest(ev);
8109
+ if (ev.kind === "assistant_text") {
8110
+ this.lastRunText += `${ev.payload.text}
8111
+ `;
8112
+ }
8096
8113
  if (ev.source === "agent")
8097
8114
  this.cliRunner?.record(ev);
8098
8115
  if (ev.kind === "error") {
@@ -8180,6 +8197,8 @@ var init_worker = __esm(() => {
8180
8197
  init_process_group();
8181
8198
  init_progress_tracker();
8182
8199
  init_prompt();
8200
+ init_review_completion();
8201
+ init_review_knowledge();
8183
8202
  init_run_log();
8184
8203
  init_sdk_agent_runner();
8185
8204
  init_stage_advance();
package/dist/index.js CHANGED
@@ -7087,6 +7087,9 @@ function buildStagePreamble(stage) {
7087
7087
  }
7088
7088
  }
7089
7089
  lines.push("Do only this stage's work. When the stage's handoff is met, end your session — advancement to the next stage is handled by the board.");
7090
+ if (normalizeGateSpec(stage.gate)?.kind === "review_passed") {
7091
+ lines.push("", "**This stage's gate is `review_passed` — your deliverable is a review verdict, not a prose handoff.** Do NOT end the session until you have actually reviewed the change and emitted EXACTLY one JSON block as the LAST thing you output (nothing after it):", "```json", REVIEW_VERDICT_SCHEMA, "```", "Decision rules:", REVIEW_DECISION_RULES, "The board reads this verdict to decide advancement: `approved` advances the card, `rejected` sends it back. A missing or unparseable verdict blocks the card. Do NOT modify any code — this is a read-only review.");
7092
+ }
7090
7093
  return lines.filter(Boolean).join(`
7091
7094
  `);
7092
7095
  }
@@ -7131,6 +7134,7 @@ class Worker {
7131
7134
  lastDrainedSeq = 0;
7132
7135
  runCostCents = 0;
7133
7136
  runTurns = 0;
7137
+ lastRunText = "";
7134
7138
  constructor(id, config, client, agentId, onDone, workspaceId, projectId, stateStore, onCardCompleted, onApiError) {
7135
7139
  this.config = config;
7136
7140
  this.client = client;
@@ -7199,6 +7203,7 @@ class Worker {
7199
7203
  this.completionStarted = false;
7200
7204
  this.runCostCents = 0;
7201
7205
  this.runTurns = 0;
7206
+ this.lastRunText = "";
7202
7207
  this.cliSessionId = null;
7203
7208
  this.lastDrainedSeq = 0;
7204
7209
  this.cardId = card.id;
@@ -7651,6 +7656,10 @@ class Worker {
7651
7656
  log.info(this.tag, `Stage "${stage.name}" gate "${gate.kind}" is advisory — skipping enforcement`);
7652
7657
  return null;
7653
7658
  }
7659
+ const review = gate.kind === "review_passed" ? parseReviewOutput(this.lastRunText) : undefined;
7660
+ if (review) {
7661
+ log.info(this.tag, `Review-gated stage "${stage.name}" verdict: ${review.verdict} (${review.findings.length} finding(s))`);
7662
+ }
7654
7663
  const registry = buildGateCollectorRegistry({
7655
7664
  build: {
7656
7665
  worktreePath,
@@ -7661,7 +7670,8 @@ class Worker {
7661
7670
  worktreePath,
7662
7671
  artifactType: stage.artifact_type
7663
7672
  },
7664
- checklist: { subtasks, cardDone: card.done ?? false }
7673
+ checklist: { subtasks, cardDone: card.done ?? false },
7674
+ ...review ? { review } : {}
7665
7675
  });
7666
7676
  const context = {
7667
7677
  cardId: card.id,
@@ -7999,6 +8009,9 @@ class Worker {
7999
8009
  });
8000
8010
  }
8001
8011
  }
8012
+ parser.on("text", (content) => {
8013
+ this.lastRunText += content;
8014
+ });
8002
8015
  parser.on("parse_error", (msg) => {
8003
8016
  log.debug(this.tag, `Stream parse error (non-fatal): ${msg}`);
8004
8017
  runLog?.stream.write(`
@@ -8092,6 +8105,10 @@ class Worker {
8092
8105
  try {
8093
8106
  for await (const ev of stream) {
8094
8107
  this.progressTracker?.ingest(ev);
8108
+ if (ev.kind === "assistant_text") {
8109
+ this.lastRunText += `${ev.payload.text}
8110
+ `;
8111
+ }
8095
8112
  if (ev.source === "agent")
8096
8113
  this.cliRunner?.record(ev);
8097
8114
  if (ev.kind === "error") {
@@ -8179,6 +8196,8 @@ var init_worker = __esm(() => {
8179
8196
  init_process_group();
8180
8197
  init_progress_tracker();
8181
8198
  init_prompt();
8199
+ init_review_completion();
8200
+ init_review_knowledge();
8182
8201
  init_run_log();
8183
8202
  init_sdk_agent_runner();
8184
8203
  init_stage_advance();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gethmy/agent",
3
- "version": "1.14.3",
3
+ "version": "1.14.4",
4
4
  "description": "Push-based agent daemon for Harmony — watches board assignments and spawns Claude CLI workers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",