@on-par/factory-cli 0.9.8-next.6 → 0.9.8-next.60
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/daemon-launchctl.d.ts +18 -0
- package/dist/cli/daemon-launchctl.d.ts.map +1 -0
- package/dist/cli/daemon-launchctl.js +33 -0
- package/dist/cli/daemon-launchctl.js.map +1 -0
- package/dist/cli/daemon.d.ts +4 -1
- package/dist/cli/daemon.d.ts.map +1 -1
- package/dist/cli/daemon.js +6 -4
- package/dist/cli/daemon.js.map +1 -1
- package/dist/cli/doctor-harness.d.ts +11 -0
- package/dist/cli/doctor-harness.d.ts.map +1 -1
- package/dist/cli/doctor-harness.js +43 -1
- package/dist/cli/doctor-harness.js.map +1 -1
- package/dist/cli/doctor-opencode-probe.d.ts +22 -0
- package/dist/cli/doctor-opencode-probe.d.ts.map +1 -0
- package/dist/cli/doctor-opencode-probe.js +110 -0
- package/dist/cli/doctor-opencode-probe.js.map +1 -0
- package/dist/cli/doctor.d.ts +30 -8
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +113 -43
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/first-run.d.ts +3 -1
- package/dist/cli/first-run.d.ts.map +1 -1
- package/dist/cli/first-run.js +5 -2
- package/dist/cli/first-run.js.map +1 -1
- package/dist/cli/github-stub.js +1 -1
- package/dist/cli/github-stub.js.map +1 -1
- package/dist/cli/harness-check.d.ts +27 -0
- package/dist/cli/harness-check.d.ts.map +1 -0
- package/dist/cli/harness-check.js +58 -0
- package/dist/cli/harness-check.js.map +1 -0
- package/dist/cli/help-groups.js +1 -1
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/index.d.ts +21 -18
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +62 -56
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/program-run-work.js +2 -2
- package/dist/cli/program-run-work.js.map +1 -1
- package/dist/cli/program-setup.d.ts.map +1 -1
- package/dist/cli/program-setup.js +10 -1
- package/dist/cli/program-setup.js.map +1 -1
- package/dist/cli/queue-add-json.d.ts +3 -1
- package/dist/cli/queue-add-json.d.ts.map +1 -1
- package/dist/cli/queue-add-json.js +1 -0
- package/dist/cli/queue-add-json.js.map +1 -1
- package/dist/cli/queue-output.d.ts +9 -0
- package/dist/cli/queue-output.d.ts.map +1 -0
- package/dist/cli/queue-output.js +38 -0
- package/dist/cli/queue-output.js.map +1 -0
- package/dist/cli/run-lane.d.ts +3 -0
- package/dist/cli/run-lane.d.ts.map +1 -1
- package/dist/cli/run-lane.js +6 -1
- package/dist/cli/run-lane.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +13 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/self-update-apply.d.ts +2 -0
- package/dist/cli/self-update-apply.d.ts.map +1 -1
- package/dist/cli/self-update-apply.js +59 -8
- package/dist/cli/self-update-apply.js.map +1 -1
- package/dist/cli/self-update.d.ts +4 -0
- package/dist/cli/self-update.d.ts.map +1 -1
- package/dist/cli/self-update.js +1 -1
- package/dist/cli/self-update.js.map +1 -1
- package/dist/cli/ship.d.ts.map +1 -1
- package/dist/cli/ship.js +17 -9
- package/dist/cli/ship.js.map +1 -1
- package/dist/cli/status.d.ts +5 -0
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +5 -4
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/stop-sentinel.d.ts +4 -0
- package/dist/cli/stop-sentinel.d.ts.map +1 -1
- package/dist/cli/stop-sentinel.js +11 -0
- package/dist/cli/stop-sentinel.js.map +1 -1
- package/dist/cli/supervise.d.ts +5 -0
- package/dist/cli/supervise.d.ts.map +1 -1
- package/dist/cli/supervise.js +1 -0
- package/dist/cli/supervise.js.map +1 -1
- package/dist/cli/triage-open-prs.d.ts +10 -0
- package/dist/cli/triage-open-prs.d.ts.map +1 -0
- package/dist/cli/triage-open-prs.js +38 -0
- package/dist/cli/triage-open-prs.js.map +1 -0
- package/dist/cli/update-state.d.ts +2 -0
- package/dist/cli/update-state.d.ts.map +1 -1
- package/dist/cli/update-state.js +14 -0
- package/dist/cli/update-state.js.map +1 -1
- package/dist/cli/worktree-reap.d.ts +31 -0
- package/dist/cli/worktree-reap.d.ts.map +1 -0
- package/dist/cli/worktree-reap.js +72 -0
- package/dist/cli/worktree-reap.js.map +1 -0
- package/package.json +3 -3
package/dist/cli/index.js
CHANGED
|
@@ -7,12 +7,15 @@ import { arch, hostname as osHostname, release, platform, userInfo } from 'node:
|
|
|
7
7
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
8
8
|
import { promisify, styleText } from 'node:util';
|
|
9
9
|
import { INVALID_BRANCH_PREFIX_MESSAGE, resolveBranchPrefixOption } from './branch-prefix.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { proposeTriageQueue } from './triage-open-prs.js';
|
|
11
|
+
import { acquirePortLease, aggregateCosts, appendKpiHistoryLine, applyRepoConfig, buildPhase, checkPhase, clearProxyState, computeHealthKpis, ConstitutionLoader, createDefaultWorkSourceRegistry, createLogger, createLaneProxy, defaultFindPortListeners, describeEffectiveConfig, detectPostMergeDefects, diagnoseModels, probeDeclaredHarnesses, estimateTrailingSpend, fetchDefectSources, fetchHumanEventSources, fetchSubscriptionUsage, formatUsageReport, getConstitutionsDir, getFactoryPaths, GITHUB_ISSUE_SOURCE, hasUnresolvedPark, InvalidArtifactsDirError, InvalidWorkRequestInputError, InvalidWorkspaceError, isCommandAvailable, isProxyRunning, kpiBranchPrefixes, kpisToHistoryRecord, laneBaseUrl, laneEnv, laneHostLabel, loadFactoryConfigForRepo, loadModelsConfig, loadRepoConfig, loadRoutesConfig, LOCAL_BRIEF_SOURCE, joinClassifierOutcomes, mergeClassifierOutcomes, parseClassifierOutcomes, summarizeClassifierOutcomes, formatClassifierReport, mergedPrRefs, ModelRegistry, ModelRouter, parkReasonFor, parseKpiHistory, parseQueue, planPhase, readEvents, readPortLeases, readQueue, readUsage, reapOrphanProcesses, reconstructKpiEvents, recordLeasePgid, releasePortLease, renderKpiReport, renderKpiTrend, resolveDefectWindowDays, parseSizeGateMode, parseMaxSlices, SIZE_GATE_MODES, resolveEffectiveModelPins, resolveEnvironmentProxy, resolveArtifactsDir, resolveLocalOnlyPolicy, resolveMergePolicy, resolveSkipCI, resolveTimeouts, resolveUsageCap, resolveWatchdogPolicy, runAutoIngest, shipPhase, formatCostTotal, validateQueue, watchUsage, writeLocalRunReport, writeProxyState, } from '@on-par/factory-core';
|
|
12
|
+
import { acquirePidFile, createCheckResumeStore, findSlicePlanComment, upsertSlicePlanComment, withSliceState, DEFAULT_GARDEN_MAX_CLUSTERS, DEFAULT_GARDEN_SINCE, capGardenClusters, clusterGarden, dedupGardenClusters, filterGardenOnlyNew, filterGardenWindow, markGardenTrackingUnknown, parseGardenDuration, readHarvestEvents, renderGardenJson, renderGardenReport, laneWorktreePath, migrateRepoConfigToYaml, REPO_CONFIG_YAML_HEADER, claudeConfigDirOverride, claudeKeychainService, cleanupWorktree, createDaemonLogSink, factoryBranchIssue, factoryBranchPrefixes, createFactorydServer, createRunRuntime, createShipExecutor, createGithubQueue, createLocalSmallDryRun, createOctokitFilingClient, createOctokitGreenPrClient, createOctokitQueueClient, daemonRuntimePaths, defaultRegistryPath, ensureDir, FACTORY_RUNTIME_CONFIG_KEYS, findUnmergedGreenPrs, formatGcReport, gitFetch, listMicroVms, listOrphanContainers, logCost, logEvent, planQueueMigration, pollBlockedParks, readCosts, readGithubQueueSnapshot, reapCleanShipWorktree, reapLaneWorktree, reapOrphanContainers, reapOrphanMicroVm, releaseRuntimeFiles, releaseStaleClaims, resolveBranchPrefix, resolveEffectiveConfig, resolveExperimental, resolveLocalOnly, resolvePrClassifierPolicy, resolveReviewFloorRules, RunLockHeldError, runOvernightQueue, parseRemoteSlug, setupWorktree, shellEscape, listBuiltInCheckers, sweepWorktrees, watchChecks, withFileLock, withGitLock, withRunLock, writePortFile, buildTriagePrompt, parseTriageCandidates, recordLocalAuthFailure, } from '@on-par/factory-core/internal';
|
|
12
13
|
import { runTui } from '@on-par/factory-tui';
|
|
13
14
|
import { admissionStateReaderFor, runQueueReconcile } from './admission.js';
|
|
14
15
|
import { cmdClassifierBacktest, ClassifierBacktestInputError, } from './classifier-backtest.js';
|
|
16
|
+
import { runHarnessCheckCommand } from './harness-check.js';
|
|
15
17
|
import { findOpenPRForIssue, landIssue } from './land.js';
|
|
18
|
+
import { STOP_SET_MESSAGE } from './stop-sentinel.js';
|
|
16
19
|
import { AwaitingReviewError, CiFailedError, CiUnverifiedError, getPullRequestLandState, LandConflictError, LandFailureError, MergeGatedError, } from './land-pr.js';
|
|
17
20
|
import { setLandRuntime } from './land-runtime.js';
|
|
18
21
|
import { cmdRun } from './run.js';
|
|
@@ -24,6 +27,7 @@ import { runQueueClear } from './queue-clear.js';
|
|
|
24
27
|
import { buildProgram } from './program.js';
|
|
25
28
|
import { buildCostJson } from './cost-json.js';
|
|
26
29
|
import { buildQueueAddJson } from './queue-add-json.js';
|
|
30
|
+
import { renderQueueAddLines, renderUnparkLines } from './queue-output.js';
|
|
27
31
|
import { buildQueueListJson } from './queue-list.js';
|
|
28
32
|
import { appendUnparkEvent, runUnpark, UnparkError } from './unpark.js';
|
|
29
33
|
import { buildRunsJson, parseRunsLimit } from './runs.js';
|
|
@@ -50,6 +54,7 @@ import { DeepCheckError, createDeepModelRunner, runIssueCheck } from './ready-ch
|
|
|
50
54
|
import { childRunSucceeded, formatChildRunSummary, runChildrenInOrder } from './run-children.js';
|
|
51
55
|
import { readRunFlagOverrides } from './run-flags.js';
|
|
52
56
|
import { runStalenessGuard } from './staleness.js';
|
|
57
|
+
import { gcWorktreeSandbox, reapParkedLane, reapPrlessShip } from './worktree-reap.js';
|
|
53
58
|
const DEFAULT_CONFIG_LOADERS = {
|
|
54
59
|
loadModelsConfig,
|
|
55
60
|
loadRoutesConfig,
|
|
@@ -96,6 +101,7 @@ const DEFAULT_INTERNAL_OPS = {
|
|
|
96
101
|
createLocalSmallDryRun,
|
|
97
102
|
readCosts,
|
|
98
103
|
sweepWorktrees,
|
|
104
|
+
reapCleanShipWorktree,
|
|
99
105
|
releaseStaleClaims,
|
|
100
106
|
pollBlockedParks,
|
|
101
107
|
findUnmergedGreenPrs,
|
|
@@ -114,6 +120,7 @@ function resolveInternalOps(overrides, base = internalOps) {
|
|
|
114
120
|
createLocalSmallDryRun: overrides.createLocalSmallDryRun ?? base.createLocalSmallDryRun,
|
|
115
121
|
readCosts: overrides.readCosts ?? base.readCosts,
|
|
116
122
|
sweepWorktrees: overrides.sweepWorktrees ?? base.sweepWorktrees,
|
|
123
|
+
reapCleanShipWorktree: overrides.reapCleanShipWorktree ?? base.reapCleanShipWorktree,
|
|
117
124
|
releaseStaleClaims: overrides.releaseStaleClaims ?? base.releaseStaleClaims,
|
|
118
125
|
pollBlockedParks: overrides.pollBlockedParks ?? base.pollBlockedParks,
|
|
119
126
|
findUnmergedGreenPrs: overrides.findUnmergedGreenPrs ?? base.findUnmergedGreenPrs,
|
|
@@ -414,7 +421,7 @@ async function cmdInit(opts = {}) {
|
|
|
414
421
|
// Doctor-style validation (policy=auto, N models reachable) — informational, never fails init.
|
|
415
422
|
const modelsConfig = applyRepoConfig(configLoaders.loadModelsConfig(), configLoaders.loadRepoConfig(repoRoot));
|
|
416
423
|
const registry = new coreOps.ModelRegistry(modelsConfig);
|
|
417
|
-
const diagnoses = coreOps.diagnoseModels(registry, modelDoctorProbes(
|
|
424
|
+
const diagnoses = coreOps.diagnoseModels(registry, modelDoctorProbes(), resolveExperimental(), resolveLocalOnly());
|
|
418
425
|
console.log(formatInitReachability(diagnoses));
|
|
419
426
|
if (!hasReachableWorker(diagnoses)) {
|
|
420
427
|
console.log(styleText('yellow', 'No worker model reachable yet — see `factory doctor` and `factory models --doctor`.'));
|
|
@@ -815,8 +822,8 @@ export function formatDoctorReport(diagnoses, repoDefined = new Set()) {
|
|
|
815
822
|
export function hasReachableWorker(diagnoses) {
|
|
816
823
|
return diagnoses.some((d) => d.reachable && (d.tiers.includes('worker') || d.tiers.includes('worker_fallback')));
|
|
817
824
|
}
|
|
818
|
-
function ollamaModelSet(
|
|
819
|
-
if (
|
|
825
|
+
function ollamaModelSet() {
|
|
826
|
+
if (!coreOps.isCommandAvailable('ollama'))
|
|
820
827
|
return undefined;
|
|
821
828
|
try {
|
|
822
829
|
const out = shellOps.execSync('ollama list', { timeout: 10_000 });
|
|
@@ -831,15 +838,21 @@ function ollamaModelSet(requireOnPath = false) {
|
|
|
831
838
|
}
|
|
832
839
|
}
|
|
833
840
|
/** Probes shared by every doctor-style reachability check (init, models --doctor, overnight
|
|
834
|
-
* preflight), so their counts agree.
|
|
835
|
-
* reaches the shell (#2507). */
|
|
836
|
-
export function modelDoctorProbes(
|
|
837
|
-
const ollamaModels = ollamaModelSet(
|
|
841
|
+
* preflight), so their counts agree. The probes never invoke `ollama` unless it is on PATH, so a
|
|
842
|
+
* missing binary never reaches the shell (#2507, #2724). */
|
|
843
|
+
export function modelDoctorProbes() {
|
|
844
|
+
const ollamaModels = ollamaModelSet();
|
|
838
845
|
return {
|
|
839
846
|
commandAvailable: coreOps.isCommandAvailable,
|
|
840
847
|
ollamaModelPresent: ollamaModels ? (model) => ollamaModels.has(model) : undefined,
|
|
841
848
|
};
|
|
842
849
|
}
|
|
850
|
+
async function cmdHarnessCheck(id, opts) {
|
|
851
|
+
const r = await runHarnessCheckCommand(id, opts, { repoRoot: await getRepoRoot(), ...configLoaders });
|
|
852
|
+
if (r.exitCode !== 0)
|
|
853
|
+
throw new CliExitError(r.output, r.exitCode);
|
|
854
|
+
console.log(r.output);
|
|
855
|
+
}
|
|
843
856
|
async function cmdModels(opts = {}) {
|
|
844
857
|
const repoRoot = await getRepoRoot();
|
|
845
858
|
const repoConfig = configLoaders.loadRepoConfig(repoRoot);
|
|
@@ -1190,16 +1203,17 @@ export function resolveUsageKnobs(env = process.env, repoConfig = null, override
|
|
|
1190
1203
|
};
|
|
1191
1204
|
}
|
|
1192
1205
|
/** Human-readable name for whatever decided the usage-watch gate, used in the `factory run`
|
|
1193
|
-
* and `factory supervise` logs so an explicit operator override is always attributable (#1404).
|
|
1194
|
-
|
|
1206
|
+
* and `factory supervise` logs so an explicit operator override is always attributable (#1404). `repoConfigLabel` names the
|
|
1207
|
+
* repo config file that was loaded (#2570). */
|
|
1208
|
+
export function usageWatchSourceLabel(source, watch, repoConfigLabel = 'the repo config') {
|
|
1195
1209
|
switch (source) {
|
|
1196
1210
|
case 'flag':
|
|
1197
1211
|
return watch ? 'flag: --usage-watch' : 'flag: --no-usage-watch';
|
|
1198
1212
|
case 'repo':
|
|
1199
|
-
return
|
|
1213
|
+
return `${repoConfigLabel}: budget.watchdog.watch`;
|
|
1200
1214
|
case 'env':
|
|
1201
1215
|
return 'env: FACTORY_USAGE_WATCH';
|
|
1202
|
-
default:
|
|
1216
|
+
case 'default':
|
|
1203
1217
|
return 'default';
|
|
1204
1218
|
}
|
|
1205
1219
|
}
|
|
@@ -1304,7 +1318,7 @@ async function cmdTui(opts = {}, runTuiImpl = runTui) {
|
|
|
1304
1318
|
const effectiveConfigLines = describeEffectiveConfig({
|
|
1305
1319
|
router,
|
|
1306
1320
|
repo: repoConfig,
|
|
1307
|
-
repoConfigPath:
|
|
1321
|
+
repoConfigPath: repoConfigFileFor(repoRoot, paths.config).relPath,
|
|
1308
1322
|
mergePolicy: resolveMergePolicy(configLoaders.loadFactoryConfigForRepo(paths.config), process.env, {
|
|
1309
1323
|
auto: readRunFlagOverrides(paths.runFlags).autoMerge,
|
|
1310
1324
|
}),
|
|
@@ -1479,14 +1493,15 @@ async function runAutoWorktreeGc(repoRoot, paths, ghRepo, eventScope) {
|
|
|
1479
1493
|
* lane holds the land lock so a sweep can never race a merge. Logs worktree-gc only when it
|
|
1480
1494
|
* removed something. Never throws. */
|
|
1481
1495
|
export async function sweepBetweenLaneIssues(issue, lane, repoRoot, ghRepo, paths, deps = {}) {
|
|
1482
|
-
const { loadConfig = configLoaders.loadFactoryConfigForRepo, sweep = internalOps.sweepWorktrees, emitEvent = logEvent, octokit = getOctokit, } = deps;
|
|
1496
|
+
const { loadConfig = configLoaders.loadFactoryConfigForRepo, sweep = internalOps.sweepWorktrees, emitEvent = logEvent, octokit = getOctokit, protectedIssues = () => new Set(), } = deps;
|
|
1483
1497
|
try {
|
|
1484
1498
|
const cfg = loadConfig(paths.config);
|
|
1485
1499
|
if (!cfg.worktree.autoGcOnRun)
|
|
1486
1500
|
return 'disabled';
|
|
1487
1501
|
const gcLog = (type, msg) => emitEvent(paths.events, type, issue, msg, { lane });
|
|
1488
1502
|
const sandbox = gcWorktreeSandbox(cfg.sandbox, repoRoot);
|
|
1489
|
-
const
|
|
1503
|
+
const gcOpts = { repoRoot, ttlDays: cfg.worktree.gcTtlDays, repo: ghRepo, branchPrefix: resolveBranchPrefix() };
|
|
1504
|
+
const report = await withGitLock(repoRoot, () => withFileLock(paths.mergeLock, () => withFileLock(paths.gitLock, () => sweep({ ...gcOpts, protectedIssues: protectedIssues() }, { log: gcLog, octokit: octokit(), sandbox })), { timeoutMs: 0 }));
|
|
1490
1505
|
if (report.removed.length > 0) {
|
|
1491
1506
|
emitEvent(paths.events, 'worktree-gc', issue, `removed ${report.removed.length} stale worktree(s), kept ${report.kept}`, { lane });
|
|
1492
1507
|
console.log(internalOps.formatGcReport(report));
|
|
@@ -1538,6 +1553,9 @@ async function cmdShip(issueNum, opts) {
|
|
|
1538
1553
|
catch (err) {
|
|
1539
1554
|
if (err instanceof IssueSkippedError)
|
|
1540
1555
|
return;
|
|
1556
|
+
if (ghRepo && !(err instanceof InvalidWorkRequestInputError) && !(err instanceof LaneEnvironmentPauseError)) {
|
|
1557
|
+
await reapPrlessShipWorktree(issueNum, repoRoot, ghRepo, paths, branchPrefix);
|
|
1558
|
+
}
|
|
1541
1559
|
// #2492: a pull request number is a usage error, not a failed ship.
|
|
1542
1560
|
if (err instanceof InvalidWorkRequestInputError)
|
|
1543
1561
|
throw new CliExitError(`factory: ${err.message}`, 2);
|
|
@@ -1853,30 +1871,23 @@ export async function withRepoRunLock(paths, command, fn, deps = {}) {
|
|
|
1853
1871
|
throw err;
|
|
1854
1872
|
}
|
|
1855
1873
|
}
|
|
1856
|
-
/** The repo's current docker-sandbox descriptor for worktree-gc sweeps, or undefined for
|
|
1857
|
-
* every other runtime/config state (including a fixture config with no `sandbox` key). */
|
|
1858
|
-
function gcWorktreeSandbox(sandboxCfg, repoRoot) {
|
|
1859
|
-
if (!sandboxCfg)
|
|
1860
|
-
return undefined;
|
|
1861
|
-
const policy = resolveSandboxPolicy(sandboxCfg, { worktree: repoRoot, repoRoot });
|
|
1862
|
-
return worktreeSandboxFor(policy?.runtime);
|
|
1863
|
-
}
|
|
1864
|
-
/** Eagerly reaps a parked lane's own worktree inside `factory run` (#1007). All the safety
|
|
1865
|
-
* gates live in reapLaneWorktree; this wrapper resolves the lane's conventional worktree
|
|
1866
|
-
* path and holds the same git+file lock pairing as every other worktree mutation site. A
|
|
1867
|
-
* reap failure is logged as a warn and never surfaces — parking must always succeed. */
|
|
1868
1874
|
export async function reapParkedLaneWorktree(issue, repoRoot, ghRepo, paths, prefixOverride) {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1875
|
+
await reapParkedLane({ configLoaders, worktreePathFor }, reapLaneWorktree, [
|
|
1876
|
+
issue,
|
|
1877
|
+
repoRoot,
|
|
1878
|
+
ghRepo,
|
|
1879
|
+
paths,
|
|
1880
|
+
prefixOverride,
|
|
1881
|
+
]);
|
|
1882
|
+
}
|
|
1883
|
+
export async function reapPrlessShipWorktree(issue, repoRoot, ghRepo, paths, prefixOverride) {
|
|
1884
|
+
await reapPrlessShip({ configLoaders, worktreePathFor }, internalOps.reapCleanShipWorktree, [
|
|
1885
|
+
issue,
|
|
1886
|
+
repoRoot,
|
|
1887
|
+
ghRepo,
|
|
1888
|
+
paths,
|
|
1889
|
+
prefixOverride,
|
|
1890
|
+
]);
|
|
1880
1891
|
}
|
|
1881
1892
|
export async function cmdWorktreeGc(opts) {
|
|
1882
1893
|
const repoRoot = await getRepoRoot();
|
|
@@ -2016,7 +2027,7 @@ async function cmdTriage(opts) {
|
|
|
2016
2027
|
onLog: (msg) => logEvent(paths.events, 'triage', '-', msg),
|
|
2017
2028
|
});
|
|
2018
2029
|
model = result.model;
|
|
2019
|
-
const queue =
|
|
2030
|
+
const queue = await proposeTriageQueue(result.output, ghRepo, paths.events, shellOps.exec);
|
|
2020
2031
|
if (queue) {
|
|
2021
2032
|
const header = triageQueueHeader(model, product);
|
|
2022
2033
|
writeFileSync(paths.queueProposed, header + queue);
|
|
@@ -2176,7 +2187,8 @@ export async function cmdUnpark(issueArg, opts = {}) {
|
|
|
2176
2187
|
console.log(JSON.stringify(result));
|
|
2177
2188
|
return;
|
|
2178
2189
|
}
|
|
2179
|
-
|
|
2190
|
+
for (const line of renderUnparkLines(result))
|
|
2191
|
+
console.log(line);
|
|
2180
2192
|
}
|
|
2181
2193
|
export async function cmdQueueAdd(lane, issueArgs, opts = {}) {
|
|
2182
2194
|
// Validate + dedupe BEFORE any GitHub call. parseIssueArg throws CliExitError(2) on bad input.
|
|
@@ -2215,17 +2227,8 @@ export async function cmdQueueAdd(lane, issueArgs, opts = {}) {
|
|
|
2215
2227
|
}
|
|
2216
2228
|
return;
|
|
2217
2229
|
}
|
|
2218
|
-
for (const
|
|
2219
|
-
|
|
2220
|
-
console.log(styleText('green', `#${r.issue} queued → lane ${lane}, position ${r.position}`));
|
|
2221
|
-
}
|
|
2222
|
-
else if (r.outcome === 'already-queued') {
|
|
2223
|
-
console.log(`#${r.issue} already queued — skipped`);
|
|
2224
|
-
}
|
|
2225
|
-
else {
|
|
2226
|
-
console.error(styleText('red', `#${r.issue} failed — ${r.detail}`));
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2230
|
+
for (const line of renderQueueAddLines(lane, results))
|
|
2231
|
+
(line.stream === 'err' ? console.error : console.log)(line.text);
|
|
2229
2232
|
const failed = results.filter((r) => r.outcome === 'failed');
|
|
2230
2233
|
if (failed.length > 0) {
|
|
2231
2234
|
throw new CliExitError(`factory: ${failed.length} issue(s) failed to queue`, 1);
|
|
@@ -2849,7 +2852,7 @@ export async function cmdResumeApproved(opts = {}) {
|
|
|
2849
2852
|
}
|
|
2850
2853
|
const USAGE_UNAVAILABLE_LINE = '[factory] supervise: usage signal unavailable — proceeding without resume gate (set FACTORY_USAGE_ESTIMATOR=1 to gate on the heuristic)';
|
|
2851
2854
|
export async function superviseLoop(deps) {
|
|
2852
|
-
const { cap, resumeAt, pollMs, watch = true, watchSource = 'default', resumeAtSource = 'default', pollSource = 'default', estimator = false, stopFile, eventsFile, now, runQueue, readUsageFn = () => readUsage({ cap, estimator }), pathExists = existsSync, clearStop = (path) => rmSync(path, { force: true }), sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), emitEvent = logEvent, writeLine = (line) => console.log(line), ingest, } = deps;
|
|
2855
|
+
const { cap, resumeAt, pollMs, watch = true, watchSource = 'default', repoConfigLabel, resumeAtSource = 'default', pollSource = 'default', estimator = false, stopFile, eventsFile, now, runQueue, readUsageFn = () => readUsage({ cap, estimator }), pathExists = existsSync, clearStop = (path) => rmSync(path, { force: true }), sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), emitEvent = logEvent, writeLine = (line) => console.log(line), ingest, } = deps;
|
|
2853
2856
|
let cycle = 0;
|
|
2854
2857
|
if (resumeAtSource === 'flag') {
|
|
2855
2858
|
const detail = 'usage watchdog threshold set by flag: --usage-threshold';
|
|
@@ -2866,11 +2869,11 @@ export async function superviseLoop(deps) {
|
|
|
2866
2869
|
let pct = 0;
|
|
2867
2870
|
let source = 'unavailable';
|
|
2868
2871
|
if (!watch) {
|
|
2869
|
-
writeLine(`[factory] supervise: usage watchdog disabled (${usageWatchSourceLabel(watchSource, watch)}) — skipping resume gate`);
|
|
2872
|
+
writeLine(`[factory] supervise: usage watchdog disabled (${usageWatchSourceLabel(watchSource, watch, repoConfigLabel)}) — skipping resume gate`);
|
|
2870
2873
|
}
|
|
2871
2874
|
else {
|
|
2872
2875
|
if (watchSource === 'flag') {
|
|
2873
|
-
writeLine(`[factory] supervise: usage watchdog enabled (${usageWatchSourceLabel(watchSource, watch)}) — enforcing resume gate`);
|
|
2876
|
+
writeLine(`[factory] supervise: usage watchdog enabled (${usageWatchSourceLabel(watchSource, watch, repoConfigLabel)}) — enforcing resume gate`);
|
|
2874
2877
|
}
|
|
2875
2878
|
let reading = await readUsageFn();
|
|
2876
2879
|
if (reading === null) {
|
|
@@ -3009,7 +3012,7 @@ export async function cmdStop(opts = {}) {
|
|
|
3009
3012
|
console.log(JSON.stringify(buildStopResumeJson({ action: 'stop', repo: json.repo, before, after })));
|
|
3010
3013
|
return;
|
|
3011
3014
|
}
|
|
3012
|
-
console.log(
|
|
3015
|
+
console.log(STOP_SET_MESSAGE);
|
|
3013
3016
|
}
|
|
3014
3017
|
export async function cmdResume(issue, opts = {}) {
|
|
3015
3018
|
if (issue === undefined && opts.from !== undefined) {
|
|
@@ -3095,6 +3098,7 @@ function runSupervise(opts) {
|
|
|
3095
3098
|
createIngestHook,
|
|
3096
3099
|
cmdRun: (o) => runRun(o),
|
|
3097
3100
|
CliExitError,
|
|
3101
|
+
repoConfigFileFor,
|
|
3098
3102
|
});
|
|
3099
3103
|
}
|
|
3100
3104
|
/** `factory status` (#2798): the handler lives in ./status.ts; this binds its runtime. */
|
|
@@ -3111,6 +3115,7 @@ function runStatus(opts = {}) {
|
|
|
3111
3115
|
warnQueueDiagnostics,
|
|
3112
3116
|
errorDetail,
|
|
3113
3117
|
CliExitError,
|
|
3118
|
+
repoConfigFileFor,
|
|
3114
3119
|
});
|
|
3115
3120
|
}
|
|
3116
3121
|
/** `factory run` (#2800): the handler lives in ./run.ts; this binds its runtime. */
|
|
@@ -3165,6 +3170,7 @@ export const PROGRAM_HANDLERS = {
|
|
|
3165
3170
|
cmdMigrate,
|
|
3166
3171
|
cmdConstitution,
|
|
3167
3172
|
cmdModels,
|
|
3173
|
+
cmdHarnessCheck,
|
|
3168
3174
|
cmdDoctor: runDoctor,
|
|
3169
3175
|
cmdCost,
|
|
3170
3176
|
cmdUsage,
|