Skip to content

Commit 1de6ca5

Browse files
chore(plugin): bump version 1.101.6 -> 1.101.7
1 parent 381a487 commit 1de6ca5

4 files changed

Lines changed: 59 additions & 36 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"metadata": {
88
"description": "H·AI·K·U — universal lifecycle orchestration with hat-based workflows, completion criteria, and automatic context preservation.",
9-
"version": "1.101.6"
9+
"version": "1.101.7"
1010
},
1111
"plugins": [
1212
{

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.101.7] - 2026-04-15
9+
10+
### Fixed
11+
- External review gates now reliably coordinate with external review systems for seamless stage advancement.
12+
813
## [1.101.6] - 2026-04-14
914

1015
### Fixed

plugin/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "haiku",
3-
"version": "1.101.6",
3+
"version": "1.101.7",
44
"description": "H·AI·K·U methodology — universal lifecycle orchestration with hat-based workflows, completion criteria, and automatic context preservation.",
55
"author": {
66
"name": "GigSmart",

plugin/bin/haiku

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64441,7 +64441,7 @@ var MCP_VERSION;
6444164441
var init_version3 = __esm({
6444264442
"src/version.ts"() {
6444364443
"use strict";
64444-
MCP_VERSION = true ? "1.101.6" : "dev";
64444+
MCP_VERSION = true ? "1.101.7" : "dev";
6444564445
}
6444664446
});
6444764447

@@ -80686,20 +80686,31 @@ function resolveStageMetadata(studio, stage) {
8068680686
function checkExternalApproval(url) {
8068780687
try {
8068880688
if (url.includes("github.com") && url.includes("/pull/")) {
80689-
const state = execFileSync3(
80689+
const output = execFileSync3(
8069080690
"gh",
80691-
["pr", "view", url, "--json", "state", "-q", ".state"],
80691+
[
80692+
"pr",
80693+
"view",
80694+
url,
80695+
"--json",
80696+
"state,reviewDecision",
80697+
"-q",
80698+
"[.state, .reviewDecision]"
80699+
],
8069280700
{ encoding: "utf8", stdio: "pipe" }
8069380701
).trim();
80694-
return state === "MERGED";
80702+
const parsed = JSON.parse(output);
80703+
const [state, reviewDecision] = parsed;
80704+
return state === "MERGED" || reviewDecision === "APPROVED";
8069580705
}
8069680706
if (url.includes("gitlab") && url.includes("/merge_requests/")) {
8069780707
const output = execFileSync3(
8069880708
"glab",
8069980709
["mr", "view", url, "--output", "json"],
8070080710
{ encoding: "utf8", stdio: "pipe" }
8070180711
).trim();
80702-
return JSON.parse(output).state === "merged";
80712+
const mr = JSON.parse(output);
80713+
return mr.state === "merged" || mr.approved === true;
8070380714
}
8070480715
return false;
8070580716
} catch {
@@ -81497,8 +81508,12 @@ ${gateFailures.map(
8149781508
const stageIdx = studioStages.indexOf(currentStage);
8149881509
const nextStage = stageIdx < studioStages.length - 1 ? studioStages[stageIdx + 1] : null;
8149981510
const intentMode = intent.mode || "continuous";
81511+
const gitAvailable = isGitRepo();
8150081512
let effectiveGateType;
81501-
if (intentMode === "discrete") {
81513+
if (!gitAvailable && reviewType.includes("external")) {
81514+
const remaining = reviewType.split(",").filter((t) => t !== "external").join(",");
81515+
effectiveGateType = remaining || "ask";
81516+
} else if (intentMode === "discrete") {
8150281517
effectiveGateType = "external";
8150381518
} else if (reviewType === "auto" || reviewType === "ask") {
8150481519
effectiveGateType = "ask";
@@ -81521,35 +81536,39 @@ ${gateFailures.map(
8152181536
if (stageStatus === "completed") {
8152281537
const gateOutcome = stageState.gate_outcome || "advanced";
8152381538
if (gateOutcome === "blocked") {
81524-
const externalUrl = stageState.external_review_url || "";
81525-
if (externalUrl) {
81526-
const approved = checkExternalApproval(externalUrl);
81527-
if (approved) {
81528-
const path = stageStatePath(slug, currentStage);
81529-
const data = readJson(path);
81530-
data.gate_outcome = "advanced";
81531-
writeJson(path, data);
81532-
emitTelemetry("haiku.gate.resolved", {
81533-
intent: slug,
81534-
stage: currentStage,
81535-
gate_type: "external",
81536-
outcome: "approved"
81537-
});
81538-
} else {
81539-
return {
81540-
action: "awaiting_external_review",
81541-
intent: slug,
81542-
stage: currentStage,
81543-
external_review_url: externalUrl,
81544-
message: `Stage '${currentStage}' is awaiting external review at: ${externalUrl}. Run /haiku:pickup again after approval.`
81545-
};
81546-
}
81539+
let approved = false;
81540+
if (isGitRepo()) {
81541+
const stageBranch = `haiku/${slug}/${currentStage}`;
81542+
const mainline = `haiku/${slug}/main`;
81543+
if (isBranchMerged(stageBranch, mainline)) {
81544+
approved = true;
81545+
}
81546+
}
81547+
if (!approved) {
81548+
const externalUrl = stageState.external_review_url || "";
81549+
if (externalUrl) {
81550+
approved = checkExternalApproval(externalUrl);
81551+
}
81552+
}
81553+
if (approved) {
81554+
const path = stageStatePath(slug, currentStage);
81555+
const data = readJson(path);
81556+
data.gate_outcome = "advanced";
81557+
writeJson(path, data);
81558+
emitTelemetry("haiku.gate.resolved", {
81559+
intent: slug,
81560+
stage: currentStage,
81561+
gate_type: "external",
81562+
outcome: "approved"
81563+
});
8154781564
} else {
81565+
const externalUrl = stageState.external_review_url || "";
8154881566
return {
8154981567
action: "awaiting_external_review",
8155081568
intent: slug,
8155181569
stage: currentStage,
81552-
message: `Stage '${currentStage}' is awaiting external review. Provide the review URL via haiku_stage_set or run /haiku:revisit to re-enter the gate.`
81570+
...externalUrl ? { external_review_url: externalUrl } : {},
81571+
message: externalUrl ? `Stage '${currentStage}' is awaiting external review at: ${externalUrl}. Neither branch merge detection nor CLI-based check detected approval yet. Run /haiku:pickup after the review is approved.` : `Stage '${currentStage}' is awaiting external review but no review URL was recorded. Run /haiku:pickup after the review is approved.`
8155381572
};
8155481573
}
8155581574
}
@@ -82632,12 +82651,11 @@ ${content}`);
8263282651
sections.push(
8263382652
`## Awaiting External Review
8263482653

82635-
${externalUrl ? `The stage is awaiting external review at: ${externalUrl}
82654+
${externalUrl ? `The stage is awaiting external review at: ${externalUrl}` : "The stage is awaiting external review but no review URL has been recorded."}
8263682655

82637-
` : "The stage is awaiting external review but no review URL has been recorded.\n\n"}Ask the user for the status of the external review. If approved, call \`haiku_run_next { intent: "${slug}" }\` \u2014 the FSM will detect the approval and advance.
82656+
The orchestrator checks for approval automatically (branch merge detection + URL-based CLI probing). Neither detected approval yet.
8263882657

82639-
${externalUrl ? "" : `If the user provides a review URL, pass it: \`haiku_run_next { intent: "${slug}", external_review_url: "<url>" }\`
82640-
`}`
82658+
Inform the user that the stage is waiting on external review. After the review is approved, run \`/haiku:pickup\` to continue.`
8264182659
);
8264282660
break;
8264382661
}

0 commit comments

Comments
 (0)