ralphctl 0.4.1 → 0.4.3
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/README.md +13 -11
- package/dist/{add-CIM72NE3.mjs → add-MG26JWBP.mjs} +6 -6
- package/dist/{add-GX7P7XTT.mjs → add-ZZYL4BSF.mjs} +5 -4
- package/dist/chunk-2FT37OZX.mjs +1071 -0
- package/dist/{chunk-CTP2A436.mjs → chunk-D2HWXEHH.mjs} +9 -2
- package/dist/{chunk-JOQO4HMM.mjs → chunk-EGUFQNRB.mjs} +10 -10
- package/dist/{chunk-3HJNVQ7N.mjs → chunk-LCY32RW4.mjs} +621 -976
- package/dist/{chunk-NUYQK5MN.mjs → chunk-LDSG7G2T.mjs} +1 -1
- package/dist/{chunk-7JLZQICD.mjs → chunk-MDE6KPJQ.mjs} +6 -6
- package/dist/{chunk-3QBEBKMZ.mjs → chunk-Q4AVHUZL.mjs} +7 -7
- package/dist/{chunk-YCDUVPRT.mjs → chunk-RQGD5WS6.mjs} +4 -72
- package/dist/{chunk-D2YGPLIV.mjs → chunk-TDBEEHTS.mjs} +213 -8
- package/dist/{chunk-SM4GGZSU.mjs → chunk-WOMGKKZY.mjs} +152 -179
- package/dist/{chunk-FKMKOWLA.mjs → chunk-WZTY77GY.mjs} +75 -1
- package/dist/cli.mjs +68 -19
- package/dist/{create-7WFSCMP4.mjs → create-PQK6KKRD.mjs} +5 -5
- package/dist/{handle-BBAZJ44Y.mjs → handle-SYVCFI6Y.mjs} +1 -1
- package/dist/{mount-2N6H5CWA.mjs → mount-2ANLHHQE.mjs} +556 -318
- package/dist/{project-2IE7VWDB.mjs → project-JF47ZWMF.mjs} +2 -2
- package/dist/prompts/check-script-discover.md +69 -0
- package/dist/prompts/ideate-auto.md +26 -1
- package/dist/prompts/ideate.md +5 -1
- package/dist/prompts/plan-auto.md +30 -2
- package/dist/prompts/plan-common-examples.md +82 -0
- package/dist/prompts/plan-common.md +26 -78
- package/dist/prompts/plan-interactive.md +6 -2
- package/dist/prompts/repo-onboard.md +111 -0
- package/dist/prompts/sprint-feedback.md +6 -2
- package/dist/prompts/task-evaluation.md +25 -10
- package/dist/prompts/task-execution.md +13 -13
- package/dist/prompts/ticket-refine.md +4 -0
- package/dist/prompts/validation-checklist.md +4 -0
- package/dist/{resolver-EOE5WUMV.mjs → resolver-PG2DZEBX.mjs} +3 -3
- package/dist/{sprint-OGOFEJJH.mjs → sprint-54DOSIJK.mjs} +3 -3
- package/dist/{start-IUDCXIEA.mjs → start-2SZTBKGF.mjs} +7 -5
- package/package.json +6 -6
|
@@ -2,27 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PromptCancelledError,
|
|
4
4
|
addCheckScriptToRepository,
|
|
5
|
-
escapableSelect
|
|
6
|
-
|
|
5
|
+
escapableSelect,
|
|
6
|
+
getAllConfigSchemaEntries,
|
|
7
|
+
getConfigDefaultValue,
|
|
8
|
+
parseConfigValue
|
|
9
|
+
} from "./chunk-TDBEEHTS.mjs";
|
|
7
10
|
import {
|
|
8
11
|
editorInput
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MDE6KPJQ.mjs";
|
|
10
13
|
import {
|
|
11
|
-
addProjectRepo,
|
|
12
|
-
getProject,
|
|
13
|
-
getProjectById,
|
|
14
|
-
getRepoById,
|
|
15
|
-
listProjects,
|
|
16
|
-
removeProject,
|
|
17
|
-
removeProjectRepo,
|
|
18
|
-
resolveRepoPath
|
|
19
|
-
} from "./chunk-NUYQK5MN.mjs";
|
|
20
|
-
import {
|
|
21
|
-
SignalParser,
|
|
22
14
|
addTask,
|
|
23
15
|
areAllTasksDone,
|
|
24
16
|
branchExists,
|
|
25
|
-
buildTicketRefinePrompt,
|
|
26
17
|
createIdeatePipeline,
|
|
27
18
|
createPlanPipeline,
|
|
28
19
|
createRefinePipeline,
|
|
@@ -40,19 +31,23 @@ import {
|
|
|
40
31
|
isGlabAvailable,
|
|
41
32
|
listTasks,
|
|
42
33
|
parseRequirementsFile,
|
|
43
|
-
processLifecycleAdapter,
|
|
44
|
-
providerDisplayName,
|
|
45
34
|
removeTask,
|
|
46
35
|
renderParsedTasksTable,
|
|
47
36
|
reorderByDependencies,
|
|
48
37
|
reorderTask,
|
|
49
|
-
resolveProvider,
|
|
50
38
|
runAiSession,
|
|
51
39
|
saveTasks,
|
|
52
40
|
updateTask,
|
|
53
41
|
updateTaskStatus,
|
|
54
42
|
validateImportTasks
|
|
55
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-LCY32RW4.mjs";
|
|
44
|
+
import {
|
|
45
|
+
SignalParser,
|
|
46
|
+
buildTicketRefinePrompt,
|
|
47
|
+
processLifecycleAdapter,
|
|
48
|
+
providerDisplayName,
|
|
49
|
+
resolveProvider
|
|
50
|
+
} from "./chunk-2FT37OZX.mjs";
|
|
56
51
|
import {
|
|
57
52
|
fetchIssueFromUrl,
|
|
58
53
|
formatIssueContext,
|
|
@@ -63,7 +58,7 @@ import {
|
|
|
63
58
|
removeTicket,
|
|
64
59
|
truncate,
|
|
65
60
|
updateTicket
|
|
66
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-EGUFQNRB.mjs";
|
|
67
62
|
import {
|
|
68
63
|
EXIT_ERROR,
|
|
69
64
|
exitWithCode
|
|
@@ -72,33 +67,33 @@ import {
|
|
|
72
67
|
getPrompt,
|
|
73
68
|
getSharedDeps
|
|
74
69
|
} from "./chunk-747KW2RW.mjs";
|
|
70
|
+
import {
|
|
71
|
+
addProjectRepo,
|
|
72
|
+
getProject,
|
|
73
|
+
getProjectById,
|
|
74
|
+
getRepoById,
|
|
75
|
+
listProjects,
|
|
76
|
+
removeProject,
|
|
77
|
+
removeProjectRepo,
|
|
78
|
+
resolveRepoPath
|
|
79
|
+
} from "./chunk-LDSG7G2T.mjs";
|
|
75
80
|
import {
|
|
76
81
|
activateSprint,
|
|
77
82
|
assertSprintStatus,
|
|
78
83
|
closeSprint,
|
|
79
84
|
createSprint,
|
|
80
85
|
deleteSprint,
|
|
81
|
-
getAiProvider,
|
|
82
|
-
getConfig,
|
|
83
|
-
getCurrentSprint,
|
|
84
86
|
getCurrentSprintOrThrow,
|
|
85
|
-
getEditor,
|
|
86
|
-
getEvaluationIterations,
|
|
87
87
|
getProgress,
|
|
88
88
|
getSprint,
|
|
89
89
|
listSprints,
|
|
90
90
|
logProgress,
|
|
91
91
|
logSprintBaselines,
|
|
92
92
|
resolveSprintId,
|
|
93
|
-
saveConfig,
|
|
94
93
|
saveSprint,
|
|
95
|
-
setAiProvider,
|
|
96
|
-
setCurrentSprint,
|
|
97
|
-
setEditor,
|
|
98
|
-
setEvaluationIterations,
|
|
99
94
|
summarizeProgressForContext,
|
|
100
95
|
withFileLock
|
|
101
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-RQGD5WS6.mjs";
|
|
102
97
|
import {
|
|
103
98
|
DETAIL_LABEL_WIDTH,
|
|
104
99
|
badge,
|
|
@@ -111,6 +106,11 @@ import {
|
|
|
111
106
|
fieldMultiline,
|
|
112
107
|
formatSprintStatus,
|
|
113
108
|
formatTaskStatus,
|
|
109
|
+
getAiProvider,
|
|
110
|
+
getConfig,
|
|
111
|
+
getCurrentSprint,
|
|
112
|
+
getEditor,
|
|
113
|
+
getEvaluationIterations,
|
|
114
114
|
getQuoteForContext,
|
|
115
115
|
horizontalLine,
|
|
116
116
|
icons,
|
|
@@ -123,6 +123,11 @@ import {
|
|
|
123
123
|
progressBar,
|
|
124
124
|
renderCard,
|
|
125
125
|
renderTable,
|
|
126
|
+
saveConfig,
|
|
127
|
+
setAiProvider,
|
|
128
|
+
setCurrentSprint,
|
|
129
|
+
setEditor,
|
|
130
|
+
setEvaluationIterations,
|
|
126
131
|
showEmpty,
|
|
127
132
|
showError,
|
|
128
133
|
showNextStep,
|
|
@@ -133,13 +138,14 @@ import {
|
|
|
133
138
|
showWarning,
|
|
134
139
|
success,
|
|
135
140
|
terminalBell
|
|
136
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-WZTY77GY.mjs";
|
|
137
142
|
import {
|
|
138
143
|
ensureError,
|
|
139
144
|
unwrapOrThrow,
|
|
140
145
|
wrapAsync
|
|
141
146
|
} from "./chunk-IWXBJD2D.mjs";
|
|
142
147
|
import {
|
|
148
|
+
CURRENT_ONBOARDING_VERSION,
|
|
143
149
|
ImportTasksSchema,
|
|
144
150
|
RequirementStatusSchema,
|
|
145
151
|
SprintSchema,
|
|
@@ -162,7 +168,7 @@ import {
|
|
|
162
168
|
getTasksFilePath,
|
|
163
169
|
readValidatedJson,
|
|
164
170
|
validateProjectPath
|
|
165
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-D2HWXEHH.mjs";
|
|
166
172
|
import {
|
|
167
173
|
NoCurrentSprintError,
|
|
168
174
|
ProjectNotFoundError,
|
|
@@ -170,14 +176,13 @@ import {
|
|
|
170
176
|
SprintStatusError,
|
|
171
177
|
StorageError,
|
|
172
178
|
TaskNotFoundError,
|
|
173
|
-
TicketNotFoundError
|
|
174
|
-
ValidationError
|
|
179
|
+
TicketNotFoundError
|
|
175
180
|
} from "./chunk-57UWLHRH.mjs";
|
|
176
181
|
|
|
177
182
|
// package.json
|
|
178
183
|
var package_default = {
|
|
179
184
|
name: "ralphctl",
|
|
180
|
-
version: "0.4.
|
|
185
|
+
version: "0.4.3",
|
|
181
186
|
description: "Agent harness for long-running AI coding tasks \u2014 orchestrates Claude Code & GitHub Copilot across repositories",
|
|
182
187
|
homepage: "https://github.com/lukas-grigis/ralphctl",
|
|
183
188
|
type: "module",
|
|
@@ -245,8 +250,8 @@ var package_default = {
|
|
|
245
250
|
"@types/node": "^25.6.0",
|
|
246
251
|
"@types/react": "^19.2.14",
|
|
247
252
|
"@types/tabtab": "^3.0.4",
|
|
248
|
-
"@vitest/coverage-v8": "^4.1.
|
|
249
|
-
eslint: "^10.2.
|
|
253
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
254
|
+
eslint: "^10.2.1",
|
|
250
255
|
"eslint-config-prettier": "^10.1.8",
|
|
251
256
|
globals: "^17.5.0",
|
|
252
257
|
husky: "^9.1.7",
|
|
@@ -256,11 +261,11 @@ var package_default = {
|
|
|
256
261
|
tsup: "^8.5.1",
|
|
257
262
|
tsx: "^4.21.0",
|
|
258
263
|
typescript: "^5.9.3",
|
|
259
|
-
"typescript-eslint": "^8.
|
|
260
|
-
vitest: "^4.1.
|
|
264
|
+
"typescript-eslint": "^8.59.0",
|
|
265
|
+
vitest: "^4.1.5"
|
|
261
266
|
},
|
|
262
267
|
"lint-staged": {
|
|
263
|
-
"*.ts": [
|
|
268
|
+
"*.{ts,tsx}": [
|
|
264
269
|
"eslint --cache --fix",
|
|
265
270
|
"prettier --write"
|
|
266
271
|
],
|
|
@@ -1897,7 +1902,7 @@ async function selectProject(message = "Select project:") {
|
|
|
1897
1902
|
default: true
|
|
1898
1903
|
});
|
|
1899
1904
|
if (create) {
|
|
1900
|
-
const { projectAddCommand } = await import("./add-
|
|
1905
|
+
const { projectAddCommand } = await import("./add-ZZYL4BSF.mjs");
|
|
1901
1906
|
await projectAddCommand({ interactive: true });
|
|
1902
1907
|
const updated = await listProjects();
|
|
1903
1908
|
if (updated.length === 0) return null;
|
|
@@ -1932,7 +1937,7 @@ async function selectSprint(message = "Select sprint:", filter) {
|
|
|
1932
1937
|
default: true
|
|
1933
1938
|
});
|
|
1934
1939
|
if (create) {
|
|
1935
|
-
const { sprintCreateCommand } = await import("./create-
|
|
1940
|
+
const { sprintCreateCommand } = await import("./create-PQK6KKRD.mjs");
|
|
1936
1941
|
await sprintCreateCommand({ interactive: true });
|
|
1937
1942
|
const updated = await listSprints();
|
|
1938
1943
|
const refiltered = filter ? updated.filter((s) => filter.includes(s.status)) : updated;
|
|
@@ -1967,7 +1972,7 @@ async function selectTicket(message = "Select ticket:", filter) {
|
|
|
1967
1972
|
default: true
|
|
1968
1973
|
});
|
|
1969
1974
|
if (create) {
|
|
1970
|
-
const { ticketAddCommand } = await import("./add-
|
|
1975
|
+
const { ticketAddCommand } = await import("./add-MG26JWBP.mjs");
|
|
1971
1976
|
await ticketAddCommand({ interactive: true });
|
|
1972
1977
|
const updated = await listTickets();
|
|
1973
1978
|
const refiltered = filter ? updated.filter(filter) : updated;
|
|
@@ -4615,136 +4620,6 @@ async function progressShowCommand() {
|
|
|
4615
4620
|
console.log(content);
|
|
4616
4621
|
}
|
|
4617
4622
|
|
|
4618
|
-
// src/integration/config/schema-provider.ts
|
|
4619
|
-
import { Result as Result6 } from "typescript-result";
|
|
4620
|
-
|
|
4621
|
-
// src/domain/config-schema.ts
|
|
4622
|
-
var ConfigSchemaDefinition = {
|
|
4623
|
-
currentSprint: {
|
|
4624
|
-
key: "currentSprint",
|
|
4625
|
-
label: "Current Sprint",
|
|
4626
|
-
type: "string",
|
|
4627
|
-
default: null,
|
|
4628
|
-
description: "Currently active sprint ID (set by `sprint start`, cleared on `sprint close`)",
|
|
4629
|
-
validation: (val) => val === null || typeof val === "string" && val.length > 0,
|
|
4630
|
-
scope: "global"
|
|
4631
|
-
},
|
|
4632
|
-
aiProvider: {
|
|
4633
|
-
key: "aiProvider",
|
|
4634
|
-
label: "AI Provider",
|
|
4635
|
-
type: "enum",
|
|
4636
|
-
enum: ["claude", "copilot"],
|
|
4637
|
-
default: null,
|
|
4638
|
-
description: "AI provider for task execution (Claude Code or GitHub Copilot CLI)",
|
|
4639
|
-
validation: (val) => val === null || typeof val === "string" && ["claude", "copilot"].includes(val),
|
|
4640
|
-
scope: "global"
|
|
4641
|
-
},
|
|
4642
|
-
evaluationIterations: {
|
|
4643
|
-
key: "evaluationIterations",
|
|
4644
|
-
label: "Evaluation Iterations",
|
|
4645
|
-
type: "integer",
|
|
4646
|
-
min: 0,
|
|
4647
|
-
max: 10,
|
|
4648
|
-
default: 1,
|
|
4649
|
-
description: "Number of fix-attempt iterations after initial evaluation; 0 = disabled. Higher values allow more refinement rounds.",
|
|
4650
|
-
validation: (val) => typeof val === "number" && Number.isInteger(val) && val >= 0 && val <= 10,
|
|
4651
|
-
scope: "sprint"
|
|
4652
|
-
}
|
|
4653
|
-
// Phase 2+ additions can be added here as single schema entries
|
|
4654
|
-
// maxTaskTurns: { ... },
|
|
4655
|
-
// checkScriptTimeout: { ... },
|
|
4656
|
-
};
|
|
4657
|
-
function getSchemaEntry(key) {
|
|
4658
|
-
return ConfigSchemaDefinition[key];
|
|
4659
|
-
}
|
|
4660
|
-
function getAllSchemaEntries() {
|
|
4661
|
-
return Object.values(ConfigSchemaDefinition);
|
|
4662
|
-
}
|
|
4663
|
-
function getDefaultValue(key) {
|
|
4664
|
-
return ConfigSchemaDefinition[key].default;
|
|
4665
|
-
}
|
|
4666
|
-
|
|
4667
|
-
// src/integration/config/schema-provider.ts
|
|
4668
|
-
function getAllConfigSchemaEntries() {
|
|
4669
|
-
return getAllSchemaEntries();
|
|
4670
|
-
}
|
|
4671
|
-
function getConfigSchemaEntry(key) {
|
|
4672
|
-
return getSchemaEntry(key);
|
|
4673
|
-
}
|
|
4674
|
-
function getConfigDefaultValue(key) {
|
|
4675
|
-
return getDefaultValue(key);
|
|
4676
|
-
}
|
|
4677
|
-
function validateConfigValue(key, value) {
|
|
4678
|
-
if (!(key in ConfigSchemaDefinition)) {
|
|
4679
|
-
return Result6.error(new ValidationError(`Unknown config key: ${key}`, key));
|
|
4680
|
-
}
|
|
4681
|
-
const schemaKey = key;
|
|
4682
|
-
const entry = getConfigSchemaEntry(schemaKey);
|
|
4683
|
-
if (!entry.validation(value)) {
|
|
4684
|
-
let errorMsg = `Invalid value for ${key}`;
|
|
4685
|
-
if (entry.type === "enum" && entry.enum) {
|
|
4686
|
-
errorMsg += `: must be one of ${entry.enum.join(", ")}`;
|
|
4687
|
-
} else if (entry.type === "integer" || entry.type === "number") {
|
|
4688
|
-
const constraints = [];
|
|
4689
|
-
if (entry.min !== void 0) constraints.push(`min: ${String(entry.min)}`);
|
|
4690
|
-
if (entry.max !== void 0) constraints.push(`max: ${String(entry.max)}`);
|
|
4691
|
-
if (constraints.length > 0) errorMsg += ` (${constraints.join(", ")})`;
|
|
4692
|
-
}
|
|
4693
|
-
return Result6.error(new ValidationError(errorMsg, key));
|
|
4694
|
-
}
|
|
4695
|
-
return Result6.ok(value);
|
|
4696
|
-
}
|
|
4697
|
-
function parseConfigValue(key, stringValue) {
|
|
4698
|
-
if (!(key in ConfigSchemaDefinition)) {
|
|
4699
|
-
return Result6.error(new ValidationError(`Unknown config key: ${key}`, key));
|
|
4700
|
-
}
|
|
4701
|
-
const schemaKey = key;
|
|
4702
|
-
const entry = getConfigSchemaEntry(schemaKey);
|
|
4703
|
-
let parsedValue;
|
|
4704
|
-
try {
|
|
4705
|
-
switch (entry.type) {
|
|
4706
|
-
case "string":
|
|
4707
|
-
parsedValue = stringValue === "null" ? null : stringValue;
|
|
4708
|
-
break;
|
|
4709
|
-
case "integer":
|
|
4710
|
-
parsedValue = stringValue === "null" ? null : Number.parseInt(stringValue, 10);
|
|
4711
|
-
if (Number.isNaN(parsedValue)) {
|
|
4712
|
-
return Result6.error(new ValidationError(`Expected integer for ${key}, got ${stringValue}`, key));
|
|
4713
|
-
}
|
|
4714
|
-
break;
|
|
4715
|
-
case "number":
|
|
4716
|
-
parsedValue = stringValue === "null" ? null : Number.parseFloat(stringValue);
|
|
4717
|
-
if (Number.isNaN(parsedValue)) {
|
|
4718
|
-
return Result6.error(new ValidationError(`Expected number for ${key}, got ${stringValue}`, key));
|
|
4719
|
-
}
|
|
4720
|
-
break;
|
|
4721
|
-
case "boolean":
|
|
4722
|
-
if (stringValue.toLowerCase() === "true" || stringValue === "1") {
|
|
4723
|
-
parsedValue = true;
|
|
4724
|
-
} else if (stringValue.toLowerCase() === "false" || stringValue === "0") {
|
|
4725
|
-
parsedValue = false;
|
|
4726
|
-
} else if (stringValue === "null") {
|
|
4727
|
-
parsedValue = null;
|
|
4728
|
-
} else {
|
|
4729
|
-
return Result6.error(new ValidationError(`Expected boolean for ${key}, got ${stringValue}`, key));
|
|
4730
|
-
}
|
|
4731
|
-
break;
|
|
4732
|
-
case "enum":
|
|
4733
|
-
if (stringValue === "null") {
|
|
4734
|
-
parsedValue = null;
|
|
4735
|
-
} else {
|
|
4736
|
-
parsedValue = stringValue;
|
|
4737
|
-
}
|
|
4738
|
-
break;
|
|
4739
|
-
}
|
|
4740
|
-
} catch (err) {
|
|
4741
|
-
return Result6.error(
|
|
4742
|
-
new ValidationError(`Failed to parse ${key}: ${err instanceof Error ? err.message : String(err)}`, key)
|
|
4743
|
-
);
|
|
4744
|
-
}
|
|
4745
|
-
return validateConfigValue(key, parsedValue);
|
|
4746
|
-
}
|
|
4747
|
-
|
|
4748
4623
|
// src/integration/cli/commands/config/config.ts
|
|
4749
4624
|
var KEY_ALIASES = {
|
|
4750
4625
|
provider: "aiProvider"
|
|
@@ -4820,7 +4695,7 @@ async function configShowCommand() {
|
|
|
4820
4695
|
}
|
|
4821
4696
|
|
|
4822
4697
|
// src/integration/cli/commands/doctor/doctor.ts
|
|
4823
|
-
import { access as access2, constants } from "fs/promises";
|
|
4698
|
+
import { access as access2, constants, readFile as readFile4 } from "fs/promises";
|
|
4824
4699
|
import { join as join5 } from "path";
|
|
4825
4700
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4826
4701
|
var REQUIRED_NODE_MAJOR = 24;
|
|
@@ -4935,6 +4810,90 @@ async function checkProjectPaths() {
|
|
|
4935
4810
|
}
|
|
4936
4811
|
return { name: "Project paths", status: "fail", detail: issues.join("; ") };
|
|
4937
4812
|
}
|
|
4813
|
+
function providerInstructionsRelPath(provider) {
|
|
4814
|
+
if (provider === "claude") return "CLAUDE.md";
|
|
4815
|
+
return ".github/copilot-instructions.md";
|
|
4816
|
+
}
|
|
4817
|
+
async function checkRepoOnboarding() {
|
|
4818
|
+
const projects = await listProjects();
|
|
4819
|
+
const config = await getConfig();
|
|
4820
|
+
const provider = config.aiProvider;
|
|
4821
|
+
const results = [];
|
|
4822
|
+
for (const project of projects) {
|
|
4823
|
+
for (const repo of project.repositories) {
|
|
4824
|
+
const name = `Onboarding \u2014 ${project.name}/${repo.name}`;
|
|
4825
|
+
if (!provider) {
|
|
4826
|
+
results.push({
|
|
4827
|
+
name,
|
|
4828
|
+
status: "skip",
|
|
4829
|
+
detail: "configure an AI provider to use onboarding"
|
|
4830
|
+
});
|
|
4831
|
+
continue;
|
|
4832
|
+
}
|
|
4833
|
+
const relPath = providerInstructionsRelPath(provider);
|
|
4834
|
+
const instructionsPath = join5(repo.path, relPath);
|
|
4835
|
+
const hasInstructions = await fileExists(instructionsPath);
|
|
4836
|
+
const ver = repo.onboardingVersion;
|
|
4837
|
+
if (ver == null) {
|
|
4838
|
+
if (hasInstructions) {
|
|
4839
|
+
results.push({
|
|
4840
|
+
name,
|
|
4841
|
+
status: "pass",
|
|
4842
|
+
detail: `authored ${relPath} (not harness-managed)`
|
|
4843
|
+
});
|
|
4844
|
+
} else {
|
|
4845
|
+
results.push({
|
|
4846
|
+
name,
|
|
4847
|
+
status: "skip",
|
|
4848
|
+
detail: `never onboarded \u2014 run \`ralphctl project onboard ${project.name} --repo ${repo.name}\``
|
|
4849
|
+
});
|
|
4850
|
+
}
|
|
4851
|
+
continue;
|
|
4852
|
+
}
|
|
4853
|
+
if (!hasInstructions) {
|
|
4854
|
+
results.push({
|
|
4855
|
+
name,
|
|
4856
|
+
status: "warn",
|
|
4857
|
+
detail: `onboardingVersion set but ${relPath} missing \u2014 re-run \`ralphctl project onboard\``
|
|
4858
|
+
});
|
|
4859
|
+
continue;
|
|
4860
|
+
}
|
|
4861
|
+
if (ver < CURRENT_ONBOARDING_VERSION) {
|
|
4862
|
+
results.push({
|
|
4863
|
+
name,
|
|
4864
|
+
status: "warn",
|
|
4865
|
+
detail: `onboarding v${String(ver)} < v${String(CURRENT_ONBOARDING_VERSION)} \u2014 re-run to refresh`
|
|
4866
|
+
});
|
|
4867
|
+
continue;
|
|
4868
|
+
}
|
|
4869
|
+
if (ver > CURRENT_ONBOARDING_VERSION) {
|
|
4870
|
+
results.push({
|
|
4871
|
+
name,
|
|
4872
|
+
status: "warn",
|
|
4873
|
+
detail: `onboarding v${String(ver)} > v${String(CURRENT_ONBOARDING_VERSION)} \u2014 repo onboarded by a newer ralphctl version \u2014 upgrade the CLI to manage it cleanly`
|
|
4874
|
+
});
|
|
4875
|
+
continue;
|
|
4876
|
+
}
|
|
4877
|
+
let body;
|
|
4878
|
+
try {
|
|
4879
|
+
body = await readFile4(instructionsPath, "utf-8");
|
|
4880
|
+
} catch {
|
|
4881
|
+
results.push({ name, status: "warn", detail: `${relPath} unreadable \u2014 re-run \`ralphctl project onboard\`` });
|
|
4882
|
+
continue;
|
|
4883
|
+
}
|
|
4884
|
+
if (body.includes("LOW-CONFIDENCE:")) {
|
|
4885
|
+
results.push({
|
|
4886
|
+
name,
|
|
4887
|
+
status: "warn",
|
|
4888
|
+
detail: "low-confidence sections detected \u2014 re-run interactively to review"
|
|
4889
|
+
});
|
|
4890
|
+
continue;
|
|
4891
|
+
}
|
|
4892
|
+
results.push({ name, status: "pass", detail: `onboarding v${String(ver)}` });
|
|
4893
|
+
}
|
|
4894
|
+
}
|
|
4895
|
+
return results;
|
|
4896
|
+
}
|
|
4938
4897
|
async function checkEvaluationConfig() {
|
|
4939
4898
|
const config = await getConfig();
|
|
4940
4899
|
if (config.evaluationIterations == null) {
|
|
@@ -4950,6 +4909,17 @@ async function checkEvaluationConfig() {
|
|
|
4950
4909
|
detail: `evaluationIterations: ${String(config.evaluationIterations)}`
|
|
4951
4910
|
};
|
|
4952
4911
|
}
|
|
4912
|
+
async function checkAiCheckScriptDiscovery() {
|
|
4913
|
+
const config = await getConfig();
|
|
4914
|
+
if (config.aiCheckScriptDiscovery === false) {
|
|
4915
|
+
return {
|
|
4916
|
+
name: "AI check-script discovery",
|
|
4917
|
+
status: "warn",
|
|
4918
|
+
detail: "disabled \u2014 `project add` will skip the AI fallback for unrecognized ecosystems (re-enable: ralphctl config set aiCheckScriptDiscovery true)"
|
|
4919
|
+
};
|
|
4920
|
+
}
|
|
4921
|
+
return null;
|
|
4922
|
+
}
|
|
4953
4923
|
async function checkConfigSchemaValidation() {
|
|
4954
4924
|
const config = await getConfig();
|
|
4955
4925
|
const entries = getAllConfigSchemaEntries();
|
|
@@ -4999,9 +4969,14 @@ async function doctorCommand() {
|
|
|
4999
4969
|
checkProjectPaths(),
|
|
5000
4970
|
checkCurrentSprint(),
|
|
5001
4971
|
checkEvaluationConfig(),
|
|
4972
|
+
checkAiCheckScriptDiscovery(),
|
|
5002
4973
|
checkConfigSchemaValidation()
|
|
5003
4974
|
]);
|
|
5004
|
-
|
|
4975
|
+
for (const r of asyncResults) {
|
|
4976
|
+
if (r !== null) results.push(r);
|
|
4977
|
+
}
|
|
4978
|
+
const onboardingResults = await checkRepoOnboarding();
|
|
4979
|
+
results.push(...onboardingResults);
|
|
5005
4980
|
for (const result of results) {
|
|
5006
4981
|
if (result.status === "pass") {
|
|
5007
4982
|
log.success(`${result.name}${result.detail ? colors.muted(` \u2014 ${result.detail}`) : ""}`);
|
|
@@ -5225,9 +5200,6 @@ export {
|
|
|
5225
5200
|
loadDashboardData,
|
|
5226
5201
|
getNextAction,
|
|
5227
5202
|
showDashboard,
|
|
5228
|
-
getAllSchemaEntries,
|
|
5229
|
-
validateConfigValue,
|
|
5230
|
-
parseConfigValue,
|
|
5231
5203
|
configSetCommand,
|
|
5232
5204
|
configShowCommand,
|
|
5233
5205
|
checkNodeVersion,
|
|
@@ -5237,6 +5209,7 @@ export {
|
|
|
5237
5209
|
checkGlabInstalled,
|
|
5238
5210
|
checkDataDirectory,
|
|
5239
5211
|
checkProjectPaths,
|
|
5212
|
+
checkRepoOnboarding,
|
|
5240
5213
|
checkEvaluationConfig,
|
|
5241
5214
|
checkConfigSchemaValidation,
|
|
5242
5215
|
checkCurrentSprint,
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
unwrapOrThrow
|
|
4
|
+
} from "./chunk-IWXBJD2D.mjs";
|
|
5
|
+
import {
|
|
6
|
+
ConfigSchema,
|
|
7
|
+
fileExists,
|
|
8
|
+
getConfigPath,
|
|
9
|
+
readValidatedJson,
|
|
10
|
+
writeValidatedJson
|
|
11
|
+
} from "./chunk-D2HWXEHH.mjs";
|
|
2
12
|
|
|
3
13
|
// src/integration/ui/theme/theme.ts
|
|
4
14
|
import { bold, cyan, gray, green, red, yellow } from "colorette";
|
|
@@ -467,6 +477,60 @@ function renderTable(columns, rows, options = {}) {
|
|
|
467
477
|
return result.join("\n");
|
|
468
478
|
}
|
|
469
479
|
|
|
480
|
+
// src/integration/persistence/config.ts
|
|
481
|
+
var DEFAULT_EVALUATION_ITERATIONS = 1;
|
|
482
|
+
var DEFAULT_CONFIG = {
|
|
483
|
+
currentSprint: null,
|
|
484
|
+
aiProvider: null,
|
|
485
|
+
editor: null
|
|
486
|
+
};
|
|
487
|
+
async function getConfig() {
|
|
488
|
+
const configPath = getConfigPath();
|
|
489
|
+
if (!await fileExists(configPath)) {
|
|
490
|
+
return DEFAULT_CONFIG;
|
|
491
|
+
}
|
|
492
|
+
return unwrapOrThrow(await readValidatedJson(configPath, ConfigSchema));
|
|
493
|
+
}
|
|
494
|
+
async function saveConfig(config) {
|
|
495
|
+
unwrapOrThrow(await writeValidatedJson(getConfigPath(), config, ConfigSchema));
|
|
496
|
+
}
|
|
497
|
+
async function getCurrentSprint() {
|
|
498
|
+
const config = await getConfig();
|
|
499
|
+
return config.currentSprint;
|
|
500
|
+
}
|
|
501
|
+
async function setCurrentSprint(sprintId) {
|
|
502
|
+
const config = await getConfig();
|
|
503
|
+
config.currentSprint = sprintId;
|
|
504
|
+
await saveConfig(config);
|
|
505
|
+
}
|
|
506
|
+
async function getAiProvider() {
|
|
507
|
+
const config = await getConfig();
|
|
508
|
+
return config.aiProvider ?? null;
|
|
509
|
+
}
|
|
510
|
+
async function setAiProvider(provider) {
|
|
511
|
+
const config = await getConfig();
|
|
512
|
+
config.aiProvider = provider;
|
|
513
|
+
await saveConfig(config);
|
|
514
|
+
}
|
|
515
|
+
async function getEditor() {
|
|
516
|
+
const config = await getConfig();
|
|
517
|
+
return config.editor ?? null;
|
|
518
|
+
}
|
|
519
|
+
async function setEditor(editor) {
|
|
520
|
+
const config = await getConfig();
|
|
521
|
+
config.editor = editor;
|
|
522
|
+
await saveConfig(config);
|
|
523
|
+
}
|
|
524
|
+
async function getEvaluationIterations() {
|
|
525
|
+
const config = await getConfig();
|
|
526
|
+
return config.evaluationIterations ?? DEFAULT_EVALUATION_ITERATIONS;
|
|
527
|
+
}
|
|
528
|
+
async function setEvaluationIterations(iterations) {
|
|
529
|
+
const config = await getConfig();
|
|
530
|
+
config.evaluationIterations = iterations;
|
|
531
|
+
await saveConfig(config);
|
|
532
|
+
}
|
|
533
|
+
|
|
470
534
|
export {
|
|
471
535
|
emoji,
|
|
472
536
|
colors,
|
|
@@ -504,5 +568,15 @@ export {
|
|
|
504
568
|
horizontalLine,
|
|
505
569
|
renderCard,
|
|
506
570
|
progressBar,
|
|
507
|
-
renderTable
|
|
571
|
+
renderTable,
|
|
572
|
+
getConfig,
|
|
573
|
+
saveConfig,
|
|
574
|
+
getCurrentSprint,
|
|
575
|
+
setCurrentSprint,
|
|
576
|
+
getAiProvider,
|
|
577
|
+
setAiProvider,
|
|
578
|
+
getEditor,
|
|
579
|
+
setEditor,
|
|
580
|
+
getEvaluationIterations,
|
|
581
|
+
setEvaluationIterations
|
|
508
582
|
};
|