@galda/cli 0.10.32 → 0.10.33

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
@@ -3335,6 +3335,24 @@ export function shouldEscalateConnectGateHint(waitedMs, email, thresholdMs = 150
3335
3335
  return Number(waitedMs) >= thresholdMs && Boolean(String(email ?? '').trim());
3336
3336
  }
3337
3337
 
3338
+ // Whether a booting manager should auto-open a browser window. A browser only
3339
+ // ever opens for a HUMAN-launched interactive manager. Ephemeral spawns — the
3340
+ // test helper (startServer), proof/verify capture instances — must never touch
3341
+ // the user's desktop: they boot with a throwaway license-less MANAGER_HOME,
3342
+ // which reads as "not signed in" and would pop a Google sign-in window per boot
3343
+ // (2026-07-18 incident: UI goals sprayed multiple Chrome sign-in windows while
3344
+ // workers ran the test suite, because MANAGER_OPEN_BROWSER=1 leaked in from the
3345
+ // launcher env into worker→test child processes). The reliable "a human asked
3346
+ // for this" signal is a concrete MANAGER_PORT: the launcher (bin/manager-for-ai
3347
+ // .mjs) resolves a real port BEFORE spawn, while every ephemeral spawn uses
3348
+ // MANAGER_PORT=0 (OS-assigned). So port 0 is never a browser-opening boot.
3349
+ export function shouldOpenBrowserOnBoot({ openBrowser, platform, managerPort } = {}) {
3350
+ if (String(openBrowser) !== '1') return false;
3351
+ if (platform !== 'darwin') return false;
3352
+ if (String(managerPort ?? '') === '0') return false; // ephemeral / test / proof spawn
3353
+ return true;
3354
+ }
3355
+
3338
3356
  // --- device-flow (PKCE) sign-in helpers --------------------------------------
3339
3357
  // The browser no longer delivers the minted token to a live loopback port —
3340
3358
  // the engine POLLS the Worker to claim it (device-flow). PKCE ties the claim to
package/engine/server.mjs CHANGED
@@ -21,7 +21,7 @@ import { homedir } from 'node:os';
21
21
  import { fileURLToPath } from 'node:url';
22
22
  import { pathToFileURL } from 'node:url';
23
23
  import { needsProjectFolder, folderLabel, buildFolderQuestion, resolveFolderAnswer, classifyFolderTarget, buildFolderInitConfirm, isFolderInitConfirmed, needsReviewPreference, buildReviewPreferenceQuestion, resolveReviewPreferenceAnswer, routeQuestionAnswer, notUnderstoodNote, parseRelocalizedQuestion, classifyAuthProbe, authBannerText, makeSigninChallenge, parseClaimResponse } from './lib.mjs';
24
- import { parseStreamEvents, parsePlan, refinePlanTasks, findOverlappingGoal, canEditGoal, canDeleteGoal, shouldAskClarification, workerExitReason, isForcedStop, workerResultText, taskCountsAsComplete, resolveWantsPR, resolveGoalSource, buildGoalSummary, buildGoalProofMd, buildGoalPrBody, buildReviewRuleSection, nextGoalStatus, isPrMerged, isPrApproved, reviewToDoneStatus, advanceReviewGoal, revertReviewGoal, approveGoal, dismissGoal, 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, buildEphemeralSeedLog, buildEphemeralSeedProjects, trimTaskActivityForState, buildAskContext, WORKER_TOOLS, verifyCfAccessJwt, resolveIdentity, goalVisibleTo, clampParallelLimit, canStartMore, nextRunnableTasks, goalsConflict, detectConflicts, pickFoldTarget, isUiChange, shouldCaptureProof, shouldCaptureBaseline, hasTestRelevantChanges, buildExecutionPlan, buildContextHandoffSummary, buildFailurePostmortem, appendFailureMemory, latestFailurePolicy, classifyChangeRisk, checkRunBudget, usageBudgetTokens, isRateLimited, nextResumeDelay, checkFreeTierLimit, resolveEntitlement, resolveCachedEntitlement, FREE_TIER_LIMITS, QUEUED_GOAL_STATUSES, verifyLicenseToken, shouldEmitSetupCompleted, pickAnalyticsUid, shouldEmitFreeExhausted, detectRequestLanguage, isNothingVerifiable, classifyComposerIntentHeuristic, buildIntentPrompt, parseIntentResponse, buildBoardSnapshot, validateBoardSnapshot, boardIsEmpty, decideBoardPull, resolveConnectedAgents, pickAvailableAgent, pickUtilityAgent, utilityModel, liveTakeoverDecision } from './lib.mjs';
24
+ import { parseStreamEvents, parsePlan, refinePlanTasks, findOverlappingGoal, canEditGoal, canDeleteGoal, shouldAskClarification, workerExitReason, isForcedStop, workerResultText, taskCountsAsComplete, resolveWantsPR, resolveGoalSource, buildGoalSummary, buildGoalProofMd, buildGoalPrBody, buildReviewRuleSection, nextGoalStatus, isPrMerged, isPrApproved, reviewToDoneStatus, advanceReviewGoal, revertReviewGoal, approveGoal, dismissGoal, 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, buildEphemeralSeedLog, buildEphemeralSeedProjects, trimTaskActivityForState, buildAskContext, WORKER_TOOLS, verifyCfAccessJwt, resolveIdentity, goalVisibleTo, clampParallelLimit, canStartMore, nextRunnableTasks, goalsConflict, detectConflicts, pickFoldTarget, isUiChange, shouldCaptureProof, shouldCaptureBaseline, hasTestRelevantChanges, buildExecutionPlan, buildContextHandoffSummary, buildFailurePostmortem, appendFailureMemory, latestFailurePolicy, classifyChangeRisk, checkRunBudget, usageBudgetTokens, isRateLimited, nextResumeDelay, checkFreeTierLimit, resolveEntitlement, resolveCachedEntitlement, FREE_TIER_LIMITS, QUEUED_GOAL_STATUSES, verifyLicenseToken, shouldEmitSetupCompleted, pickAnalyticsUid, shouldEmitFreeExhausted, detectRequestLanguage, isNothingVerifiable, classifyComposerIntentHeuristic, buildIntentPrompt, parseIntentResponse, buildBoardSnapshot, validateBoardSnapshot, boardIsEmpty, decideBoardPull, resolveConnectedAgents, pickAvailableAgent, pickUtilityAgent, utilityModel, liveTakeoverDecision, shouldOpenBrowserOnBoot } from './lib.mjs';
25
25
  import { openPR } from './pr.mjs';
26
26
  import { runVerification, exerciseUi } from './verify.mjs';
27
27
 
@@ -4110,7 +4110,7 @@ server.listen(PORT, '127.0.0.1', () => {
4110
4110
  PORT = server.address().port; // the OS-assigned one when MANAGER_PORT=0
4111
4111
  try { server6.listen(PORT, '::1'); } catch { /* IPv6 loopback unavailable */ }
4112
4112
  console.log(`[manager] Manager for AI → http://localhost:${PORT}/?key=${ACCESS_KEY}`);
4113
- if (process.env.MANAGER_OPEN_BROWSER === '1' && process.platform === 'darwin') {
4113
+ if (shouldOpenBrowserOnBoot({ openBrowser: process.env.MANAGER_OPEN_BROWSER, platform: process.platform, managerPort: process.env.MANAGER_PORT })) {
4114
4114
  // Hosted flow (billing worker + named app configured): the user lives in
4115
4115
  // app.galda.app, driven over the relay — they must NEVER be dropped on a
4116
4116
  // localhost board or an access key (Masa 2026-07-15: 「npm→ターミナル→
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.32",
3
+ "version": "0.10.33",
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": {