@galda/cli 0.10.66 → 0.10.67

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/engine/lib.mjs CHANGED
@@ -2008,20 +2008,23 @@ export function isPrMerged({ state, mergedAt } = {}) {
2008
2008
  return state === 'MERGED' || !!mergedAt;
2009
2009
  }
2010
2010
 
2011
+ export function isPrClosed({ state, mergedAt } = {}) {
2012
+ return state === 'CLOSED' && !mergedAt;
2013
+ }
2014
+
2011
2015
  // Interpret the same `gh pr view` result's reviewDecision field
2012
2016
  // (APPROVED / CHANGES_REQUESTED / REVIEW_REQUIRED / null).
2013
2017
  export function isPrApproved({ reviewDecision } = {}) {
2014
2018
  return reviewDecision === 'APPROVED';
2015
2019
  }
2016
2020
 
2017
- // A 'review' goal whose PR merged OR was approved is done; every other goal
2018
- // status (and a still-open, unapproved PR) passes through unchanged — this
2021
+ // A 'review' goal whose PR merged OR closed is done; every other goal status
2022
+ // (including an approved but still-open PR) passes through unchanged — this
2019
2023
  // never regresses a goal out of 'review' on its own.
2020
- export function reviewToDoneStatus({ goalStatus, merged }) {
2021
- // Only an actual MERGE closes a review (= the change shipped). A GitHub PR
2022
- // *approval* must NOT auto-Done on reload you review IN the Manager, so an
2023
- // external approval silently clearing your Review was the "勝手にdone" surprise.
2024
- return goalStatus === 'review' && merged ? 'done' : goalStatus;
2024
+ export function reviewToDoneStatus({ goalStatus, merged, closed }) {
2025
+ // Merge and close both end the GitHub review lifecycle. Approval alone does
2026
+ // not: an approved but still-open PR remains actionable in Review.
2027
+ return goalStatus === 'review' && (merged || closed) ? 'done' : goalStatus;
2025
2028
  }
2026
2029
 
2027
2030
  // Build the proof PR body (EN + JA, no emoji) and the PROOF.md committed to
package/engine/server.mjs CHANGED
@@ -23,6 +23,7 @@ import { pathToFileURL } from 'node:url';
23
23
  import { needsProjectFolder, folderLabel, chooseFolderScript, parseChosenFolder, buildFolderQuestion, resolveFolderAnswer, classifyFolderTarget, buildFolderInitConfirm, isFolderInitConfirmed, needsReviewPreference, buildReviewPreferenceQuestion, resolveReviewPreferenceAnswer, routeQuestionAnswer, notUnderstoodNote, parseRelocalizedQuestion, classifyAuthProbe, authBannerText, makeSigninChallenge, parseClaimResponse, isCommandOnPath } from './lib.mjs';
24
24
  import { parseStreamEvents, parseCodexEvents, buildCodexArgs, parsePlan, refinePlanTasks, canEditGoal, canDeleteGoal, shouldAskClarification, workerExitReason, isForcedStop, taskStatusAfterVerify, workerResultText, taskCountsAsComplete, resolveWantsPR, resolveGoalSource, buildGoalSummary, buildGoalProofMd, buildGoalPrBody, buildReviewSummaryPrompt, parseReviewSummary, buildReviewRuleSection, nextGoalStatus, isPrMerged, isPrApproved, reviewToDoneStatus, advanceReviewGoal, revertReviewGoal, approveGoal, dismissGoal, rejectGoal, reopenGoal, permissionModeFor, isPlanReview, nextAfterPlanApprove, GOAL_MODES, parseSkillFrontmatter, collectSkills, retestGoal, cancelRetestGoal, computeRetestOutcome, revertGoal, planRevertActions, archiveGoal, unarchiveGoal, undismissGoal, parseNumstat, truncateDiffText, sumUsage, resolveEntryUrl, parseGitLog, diffNewCommits, replayQueueLog, reconcileOrphanGoals, reorderQueue, sortQueueByPriority, TASK_PRIORITIES, validateWorkflowColumns, DEFAULT_WORKFLOW_COLUMNS, validateReviewDefinition, DEFAULT_REVIEW_DEFINITION, resolveTestGate, buildEphemeralSeedLog, buildEphemeralSeedProjects, trimTaskActivityForState, buildAskContext, WORKER_TOOLS, workerPrompt, verifyCfAccessJwt, resolveIdentity, goalVisibleTo, clampParallelLimit, canStartMore, nextRunnableTasks, goalsConflict, detectConflicts, pickFoldTarget, hasTestRelevantChanges, parseFailingTestNames, classifyTestGate, isInconclusiveTestRun, countInfraFlakes, classifyRunFailures, classifyVerifyGate, buildExecutionPlan, buildContextHandoffSummary, buildFailurePostmortem, appendFailureMemory, latestFailurePolicy, classifyChangeRisk, checkRunBudget, usageBudgetTokens, isRateLimited, nextResumeDelay, checkFreeTierLimit, resolveEntitlement, resolveCachedEntitlement, FREE_TIER_LIMITS, QUEUED_GOAL_STATUSES, verifyLicenseToken, licenseTokenPayload, shouldRefreshLicense, shouldEmitSetupCompleted, pickAnalyticsUid, shouldEmitFreeExhausted, detectRequestLanguage, testFailureReason, manualTestRetryPrompt, isNothingVerifiable, classifyComposerIntentHeuristic, detectPauseIntent, buildIntentPrompt, parseIntentResponse, buildBoardSnapshot, validateBoardSnapshot, boardIsEmpty, decideBoardPull, resolveConnectedAgents, pickAvailableAgent, pickUtilityAgent, utilityModel, liveTakeoverDecision, shouldOpenBrowserOnBoot, goalTaskTitle, buildGoalTask, RUN_DECL_FILE, parseRunDeclaration, SHOT_DIR, collectShotNames, parseGoalAddress, REPLY_OUTCOMES, REPLY_INTENTS, buildReplyIntentPrompt, parseReplyIntent, buildGoalMessage, serializeGoalMessage, parseGoalMessages } from './lib.mjs';
25
25
  import { createSerialQueue } from './lib.mjs';
26
+ import { isPrClosed } from './lib.mjs';
26
27
  import { collectProjectRules } from './lib.mjs';
27
28
  import { FALLBACK_CODEX_MODELS, loadCodexModels } from './codex-models.mjs';
28
29
  import { CLAUDE_MODELS } from './claude-models.mjs';
@@ -1400,7 +1401,7 @@ async function syncAllExternal() {
1400
1401
  }
1401
1402
 
1402
1403
  // Goals awaiting review carry their PR url in goal.pr; poll `gh pr view` for
1403
- // each and flip 'review' -> 'done' once GitHub reports it merged or approved.
1404
+ // each and flip 'review' -> 'done' once GitHub reports it merged or closed.
1404
1405
  function ghPrView(url) {
1405
1406
  return new Promise((res) => {
1406
1407
  execFile('gh', ['pr', 'view', url, '--json', 'state,mergedAt,reviewDecision'], (e, out, stderr) => {
@@ -1418,13 +1419,15 @@ async function syncGoalMerges() {
1418
1419
  if (!raw) return;
1419
1420
  let data;
1420
1421
  try { data = JSON.parse(raw); } catch { return; }
1421
- const newStatus = reviewToDoneStatus({ goalStatus: g.status, merged: isPrMerged(data), approved: isPrApproved(data) });
1422
+ const merged = isPrMerged(data);
1423
+ const closed = isPrClosed(data);
1424
+ const newStatus = reviewToDoneStatus({ goalStatus: g.status, merged, closed, approved: isPrApproved(data) });
1422
1425
  if (newStatus !== g.status) {
1423
1426
  g.status = newStatus; saveGoal(g);
1424
1427
  // §3/§7: a merged PR is truly terminal (no rework possible) — reclaim the
1425
1428
  // per-goal worktree so .manager-wt/goal-<id> doesn't leak forever. (Manual
1426
1429
  // Approve stays reworkable via revert, so we don't clean those up here.)
1427
- if (newStatus === 'done' && isPrMerged(data)) {
1430
+ if (newStatus === 'done' && (merged || closed)) {
1428
1431
  const project = projects.find((p) => p.id === g.projectId);
1429
1432
  if (project) removeGoalWorkDir(g, project);
1430
1433
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.66",
3
+ "version": "0.10.67",
4
4
  "type": "module",
5
5
  "description": "Galda - hand off work to Claude Code or Codex, get proof back. Runs on your existing subscription, no extra API cost.",
6
6
  "scripts": {