@galda/cli 0.10.107 → 0.10.108
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 +45 -0
- package/engine/server.mjs +2 -2
- package/package.json +1 -1
package/engine/lib.mjs
CHANGED
|
@@ -1896,6 +1896,51 @@ export function canStartMore(runningCount, limit) {
|
|
|
1896
1896
|
return Number.isFinite(limit) && limit > 0 && (runningCount ?? 0) < limit;
|
|
1897
1897
|
}
|
|
1898
1898
|
|
|
1899
|
+
// A goal sitting in `stacked` is not being worked on and did not fail — it is
|
|
1900
|
+
// waiting. Say why, and say what has to happen for it to start, because "nothing
|
|
1901
|
+
// is happening" is indistinguishable from "it is broken" from the outside.
|
|
1902
|
+
//
|
|
1903
|
+
// Keyed by GOAL id, not task id: a stacked goal has no task yet. That is the whole
|
|
1904
|
+
// point of the slot accounting (#541) — a goal holds its slot for as long as it is
|
|
1905
|
+
// in Doing, so the ones beyond the cap stay `stacked` instead of quietly planning
|
|
1906
|
+
// and making the board claim four things are being worked on when two are.
|
|
1907
|
+
//
|
|
1908
|
+
// The implementation of this shipped once (goal 058a11c, 2026-07-26) and was lost
|
|
1909
|
+
// when PR #396 integrated the stability roadmap: the test came across, the server
|
|
1910
|
+
// and app halves did not. main has carried a red test for it ever since.
|
|
1911
|
+
export function buildQueueWaits({ goals = [], projectPaused = () => false, projectCap = 2, globalCap = 4 } = {}) {
|
|
1912
|
+
const waits = {};
|
|
1913
|
+
const isActive = (g) => g.status === 'planning' || g.status === 'running';
|
|
1914
|
+
const activeEverywhere = goals.filter(isActive);
|
|
1915
|
+
for (const goal of goals) {
|
|
1916
|
+
if (goal?.status !== 'stacked') continue;
|
|
1917
|
+
const active = activeEverywhere.filter((g) => g.projectId === goal.projectId);
|
|
1918
|
+
if (projectPaused(goal.projectId)) {
|
|
1919
|
+
waits[goal.id] = {
|
|
1920
|
+
reason: 'this project is paused',
|
|
1921
|
+
condition: 'you resume the project',
|
|
1922
|
+
targetGoalIds: [],
|
|
1923
|
+
};
|
|
1924
|
+
} else if (active.length < projectCap && activeEverywhere.length >= globalCap) {
|
|
1925
|
+
// This project has room; the machine does not. Naming the other projects'
|
|
1926
|
+
// goals here would point at work the person may not even be looking at, so
|
|
1927
|
+
// the target stays the global limit itself.
|
|
1928
|
+
waits[goal.id] = {
|
|
1929
|
+
reason: `all ${globalCap} slots across every project are already Doing`,
|
|
1930
|
+
condition: 'one of them finishes, fails, or moves to Review',
|
|
1931
|
+
targetGoalIds: activeEverywhere.map((g) => g.id),
|
|
1932
|
+
};
|
|
1933
|
+
} else {
|
|
1934
|
+
waits[goal.id] = {
|
|
1935
|
+
reason: `all ${projectCap} project slots are already Doing`,
|
|
1936
|
+
condition: 'one of them finishes, fails, or moves to Review',
|
|
1937
|
+
targetGoalIds: active.map((g) => g.id),
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return waits;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1899
1944
|
// Pick up to `limit` tasks from the front of `waiting` that are safe to start
|
|
1900
1945
|
// RIGHT NOW, preserving same-goal ordering: a goal already represented in
|
|
1901
1946
|
// `runningGoalIds` (has an in-flight task) contributes nothing this round,
|
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, chooseFolderScript, parseChosenFolder, buildFolderQuestion, resolveFolderAnswer, classifyFolderTarget, buildFolderInitConfirm, isFolderInitConfirmed, needsReviewPreference, buildReviewPreferenceQuestion, resolveReviewPreferenceAnswer, routeQuestionAnswer, notUnderstoodNote, parseRelocalizedQuestion, classifyAuthProbe, authBannerText, makeSigninChallenge, parseClaimResponse, isCommandOnPath, hostReadiness, parseRequestedWorkspaceDir } from './lib.mjs';
|
|
24
|
-
import { parseStreamEvents, parseCodexEvents, buildCodexArgs, parsePlan, refinePlanTasks, canEditGoal, canDeleteGoal, shouldAskClarification, workerExitReason, classifyWorkerFailure, isForcedStop, taskStatusAfterVerify, workerResultText, taskCountsAsComplete, resolveWantsPR, resolveGoalSource, buildGoalSummary, buildReviewAttemptLedger, latestGoalOutcomeTask, buildDirtyWorkspacePrBlock, 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, rebasePreviewUrl, shouldCreateGoalPR, normalizePullRequestUrl, 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, autoFoldReviewsEnabled, parseGitUnifiedDiffLocations, hasTestRelevantChanges, parseFailingTestNames, classifyTestGate, classifyPrSafety, isInconclusiveTestRun, countInfraFlakes, classifyRunFailures, classifyVerifyGate, buildVerificationInfraError, verificationInfraErrorFrom, 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, isNothingVerifiableForPR, isSuspiciouslyIncompleteDone, classifyComposerIntentHeuristic, detectPauseIntent, buildIntentPrompt, parseIntentResponse, buildBoardSnapshot, validateBoardSnapshot, boardIsEmpty, decideBoardPull, resolveConnectedAgents, pickAvailableAgent, pickUtilityAgent, utilityModel, liveTakeoverDecision, shouldOpenBrowserOnBoot, goalTaskTitle, buildGoalTask, shouldUsePlannerForGoal, RUN_DECL_FILE, REQUIREMENT_EVIDENCE_FILE, parseRequirementEvidenceDocument, parseRunDeclaration, SHOT_DIR, collectShotNames, parseGoalAddress, REPLY_OUTCOMES, buildGoalMessage, serializeGoalMessage, parseGoalMessages, computeInternalQualityMetrics, classifyInternalQualityTaskError, resolveWorkspaceMode, goalSessionFor, setGoalAgentSession, switchGoalAgentSession, parseApprovalRequest } from './lib.mjs';
|
|
24
|
+
import { parseStreamEvents, parseCodexEvents, buildCodexArgs, parsePlan, refinePlanTasks, canEditGoal, canDeleteGoal, shouldAskClarification, workerExitReason, classifyWorkerFailure, isForcedStop, taskStatusAfterVerify, workerResultText, taskCountsAsComplete, resolveWantsPR, resolveGoalSource, buildGoalSummary, buildReviewAttemptLedger, latestGoalOutcomeTask, buildDirtyWorkspacePrBlock, 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, rebasePreviewUrl, shouldCreateGoalPR, normalizePullRequestUrl, 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, buildQueueWaits, nextRunnableTasks, goalsConflict, detectConflicts, pickFoldTarget, autoFoldReviewsEnabled, parseGitUnifiedDiffLocations, hasTestRelevantChanges, parseFailingTestNames, classifyTestGate, classifyPrSafety, isInconclusiveTestRun, countInfraFlakes, classifyRunFailures, classifyVerifyGate, buildVerificationInfraError, verificationInfraErrorFrom, 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, isNothingVerifiableForPR, isSuspiciouslyIncompleteDone, classifyComposerIntentHeuristic, detectPauseIntent, buildIntentPrompt, parseIntentResponse, buildBoardSnapshot, validateBoardSnapshot, boardIsEmpty, decideBoardPull, resolveConnectedAgents, pickAvailableAgent, pickUtilityAgent, utilityModel, liveTakeoverDecision, shouldOpenBrowserOnBoot, goalTaskTitle, buildGoalTask, shouldUsePlannerForGoal, RUN_DECL_FILE, REQUIREMENT_EVIDENCE_FILE, parseRequirementEvidenceDocument, parseRunDeclaration, SHOT_DIR, collectShotNames, parseGoalAddress, REPLY_OUTCOMES, buildGoalMessage, serializeGoalMessage, parseGoalMessages, computeInternalQualityMetrics, classifyInternalQualityTaskError, resolveWorkspaceMode, goalSessionFor, setGoalAgentSession, switchGoalAgentSession, parseApprovalRequest } from './lib.mjs';
|
|
25
25
|
import { migrateRequirementModel, validateRequirementModel } from './requirement-model.mjs';
|
|
26
26
|
import { buildManagerVerificationChecks, buildRequirementVerificationEvidence, mergeRequirementVerificationEvidence } from './requirement-verification.mjs';
|
|
27
27
|
import { createSerialQueue } from './lib.mjs';
|
|
@@ -4375,7 +4375,7 @@ const server = createServer(async (req, res) => {
|
|
|
4375
4375
|
const dirty = projectDirtyInfo(p.dir);
|
|
4376
4376
|
return { ...p, ...(branch ? { branch } : {}), ...dirty };
|
|
4377
4377
|
});
|
|
4378
|
-
return json(res, 200, { projects: projectsWithBranch, goals: visibleGoals, tasks: trimTaskActivityForState(visibleTasks), models: MODELS, agentModels: { 'claude-code': MODELS, codex: CODEX_MODELS }, agentEfforts: { 'claude-code': CLAUDE_EFFORTS, codex: CODEX_EFFORTS }, agents: AVAILABLE_AGENTS, connectCommand, queueOrder, externalActivity, workflowColumns: projectColumns, reviewDefinitions: projectReviewDefs, runningCounts, parallelLimits, uiVersion: uiVersion(), billing, hostReadiness: hostReadinessNow(), auth: publicAuth() });
|
|
4378
|
+
return json(res, 200, { projects: projectsWithBranch, goals: visibleGoals, tasks: trimTaskActivityForState(visibleTasks), models: MODELS, agentModels: { 'claude-code': MODELS, codex: CODEX_MODELS }, agentEfforts: { 'claude-code': CLAUDE_EFFORTS, codex: CODEX_EFFORTS }, agents: AVAILABLE_AGENTS, connectCommand, queueOrder, externalActivity, workflowColumns: projectColumns, reviewDefinitions: projectReviewDefs, runningCounts, parallelLimits, uiVersion: uiVersion(), billing, hostReadiness: hostReadinessNow(), queueWaits: buildQueueWaits({ goals: visibleGoals, projectPaused: isProjectPaused, projectCap: projectParallelCap(), globalCap: GLOBAL_MAX_PARALLEL }), auth: publicAuth() });
|
|
4379
4379
|
}
|
|
4380
4380
|
|
|
4381
4381
|
// Read-only stability snapshot: separates implementation failures from
|
package/package.json
CHANGED