@jskit-ai/jskit-cli 0.2.80 → 0.2.82
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/package.json +6 -4
- package/src/server/appBlueprint.js +1 -1
- package/src/server/commandHandlers/helperMap.js +104 -0
- package/src/server/commandHandlers/session.js +179 -4
- package/src/server/commandHandlers/show.js +169 -34
- package/src/server/core/argParser.js +20 -0
- package/src/server/core/commandCatalog.js +70 -7
- package/src/server/core/createCommandHandlers.js +4 -1
- package/src/server/helperMap.js +463 -0
- package/src/server/helperMapPaths.js +7 -0
- package/src/server/sessionRuntime/appReadiness.js +55 -0
- package/src/server/sessionRuntime/constants.js +298 -135
- package/src/server/sessionRuntime/paths.js +2 -4
- package/src/server/sessionRuntime/preconditions.js +393 -26
- package/src/server/sessionRuntime/promptRenderer.js +15 -2
- package/src/server/sessionRuntime/prompts/app_blueprint.md +26 -2
- package/src/server/sessionRuntime/prompts/automated_checks.md +42 -0
- package/src/server/sessionRuntime/prompts/deep_ui_check.md +53 -0
- package/src/server/sessionRuntime/prompts/doctor_failure.md +21 -1
- package/src/server/sessionRuntime/prompts/execute_plan.md +61 -0
- package/src/server/sessionRuntime/prompts/final_comment.md +3 -1
- package/src/server/sessionRuntime/prompts/issue_details.md +52 -0
- package/src/server/sessionRuntime/prompts/new_issue.md +34 -3
- package/src/server/sessionRuntime/prompts/plan_issue.md +81 -0
- package/src/server/sessionRuntime/prompts/pr_failure.md +14 -1
- package/src/server/sessionRuntime/prompts/review_changes.md +77 -15
- package/src/server/sessionRuntime/prompts/update_blueprint.md +36 -0
- package/src/server/sessionRuntime/prompts/user_check.md +22 -4
- package/src/server/sessionRuntime/responses.js +877 -30
- package/src/server/sessionRuntime/worktrees.js +31 -0
- package/src/server/sessionRuntime.js +2070 -244
- package/src/server/sessionRuntime/prompts/implement_issue.md +0 -25
|
@@ -13,18 +13,121 @@ const SESSION_STATUS = Object.freeze({
|
|
|
13
13
|
|
|
14
14
|
const SESSION_ID_PATTERN = /^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(?:-[a-z0-9]{4})?$/u;
|
|
15
15
|
const SESSION_STATE_RELATIVE_PATH = ".jskit/sessions";
|
|
16
|
+
const SESSION_WORKFLOW_VERSION = "6";
|
|
17
|
+
const REVIEW_PASS_LIMIT = 0;
|
|
16
18
|
const PROMPT_DIRECTORY = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "prompts");
|
|
19
|
+
const JSKIT_CLI_SHELL_COMMAND = "npx --no-install jskit";
|
|
20
|
+
const JSKIT_CLI_SHELL_RULE = [
|
|
21
|
+
"Shell command rule:",
|
|
22
|
+
"",
|
|
23
|
+
`- When running JSKIT CLI commands from the shell, use \`${JSKIT_CLI_SHELL_COMMAND} ...\`.`,
|
|
24
|
+
"- Do not run bare `jskit ...` unless you are inside an npm script where `node_modules/.bin` is on PATH.",
|
|
25
|
+
"- Do not run `npx jskit ...` without `--no-install`; it may fetch packages instead of using this app's installed CLI.",
|
|
26
|
+
"- If `npx --no-install jskit ...` is unavailable, continue with filesystem inspection when possible and report that the local JSKIT CLI is missing."
|
|
27
|
+
].join("\n");
|
|
28
|
+
const DEFAULT_NEXT_COMMAND_TEMPLATE = `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step`;
|
|
17
29
|
|
|
18
30
|
const INPUT_NONE = Object.freeze({ type: "none" });
|
|
31
|
+
const ISSUE_TITLE_INPUT = Object.freeze({
|
|
32
|
+
extract: "issue_title",
|
|
33
|
+
formatHint: "text",
|
|
34
|
+
label: "Approved issue title",
|
|
35
|
+
name: "issueTitle",
|
|
36
|
+
required: true,
|
|
37
|
+
type: "text"
|
|
38
|
+
});
|
|
19
39
|
const ISSUE_TEXT_INPUT = Object.freeze({
|
|
20
40
|
extract: "issue_text",
|
|
21
41
|
formatHint: "markdown",
|
|
22
|
-
label: "Approved issue
|
|
42
|
+
label: "Approved issue body",
|
|
23
43
|
multiline: true,
|
|
24
44
|
name: "issue",
|
|
25
45
|
required: true,
|
|
26
46
|
type: "text"
|
|
27
47
|
});
|
|
48
|
+
const ISSUE_DRAFT_INPUT = Object.freeze({
|
|
49
|
+
fields: Object.freeze([
|
|
50
|
+
ISSUE_TITLE_INPUT,
|
|
51
|
+
ISSUE_TEXT_INPUT
|
|
52
|
+
]),
|
|
53
|
+
type: "object"
|
|
54
|
+
});
|
|
55
|
+
const ISSUE_TITLE_OUTPUT = Object.freeze({
|
|
56
|
+
extract: "issue_title",
|
|
57
|
+
field: "issueTitle",
|
|
58
|
+
formatHint: "text",
|
|
59
|
+
label: "Issue title",
|
|
60
|
+
required: true
|
|
61
|
+
});
|
|
62
|
+
const ISSUE_TEXT_OUTPUT = Object.freeze({
|
|
63
|
+
extract: "issue_text",
|
|
64
|
+
field: "issue",
|
|
65
|
+
formatHint: "markdown",
|
|
66
|
+
label: "Issue body",
|
|
67
|
+
multiline: true,
|
|
68
|
+
required: true
|
|
69
|
+
});
|
|
70
|
+
const PLAN_INPUT = Object.freeze({
|
|
71
|
+
extract: "plan",
|
|
72
|
+
formatHint: "markdown",
|
|
73
|
+
label: "Approved plan",
|
|
74
|
+
multiline: true,
|
|
75
|
+
name: "plan",
|
|
76
|
+
required: true,
|
|
77
|
+
type: "text"
|
|
78
|
+
});
|
|
79
|
+
const PLAN_OUTPUT = Object.freeze({
|
|
80
|
+
extract: "plan",
|
|
81
|
+
field: "plan",
|
|
82
|
+
formatHint: "markdown",
|
|
83
|
+
label: "Plan",
|
|
84
|
+
multiline: true,
|
|
85
|
+
required: true
|
|
86
|
+
});
|
|
87
|
+
const ISSUE_DETAILS_INPUT = Object.freeze({
|
|
88
|
+
extract: "issue_details",
|
|
89
|
+
formatHint: "markdown",
|
|
90
|
+
label: "Confirmed issue details",
|
|
91
|
+
multiline: true,
|
|
92
|
+
name: "issueDetails",
|
|
93
|
+
required: true,
|
|
94
|
+
type: "text"
|
|
95
|
+
});
|
|
96
|
+
const ISSUE_DETAILS_OUTPUT = Object.freeze({
|
|
97
|
+
extract: "issue_details",
|
|
98
|
+
field: "issueDetails",
|
|
99
|
+
formatHint: "markdown",
|
|
100
|
+
label: "Issue details",
|
|
101
|
+
multiline: true,
|
|
102
|
+
required: true
|
|
103
|
+
});
|
|
104
|
+
const ISSUE_CATEGORY_OUTPUT = Object.freeze({
|
|
105
|
+
extract: "issue_category",
|
|
106
|
+
field: "issueCategory",
|
|
107
|
+
formatHint: "text",
|
|
108
|
+
label: "Issue category",
|
|
109
|
+
options: Object.freeze([
|
|
110
|
+
Object.freeze({ label: "Client", value: "client" }),
|
|
111
|
+
Object.freeze({ label: "Server", value: "server" }),
|
|
112
|
+
Object.freeze({ label: "Client and server", value: "client_server" }),
|
|
113
|
+
Object.freeze({ label: "Tooling", value: "tooling" }),
|
|
114
|
+
Object.freeze({ label: "Unknown", value: "unknown" })
|
|
115
|
+
]),
|
|
116
|
+
required: true
|
|
117
|
+
});
|
|
118
|
+
const UI_IMPACT_OUTPUT = Object.freeze({
|
|
119
|
+
extract: "ui_impact",
|
|
120
|
+
field: "uiImpact",
|
|
121
|
+
formatHint: "text",
|
|
122
|
+
label: "UI impact",
|
|
123
|
+
options: Object.freeze([
|
|
124
|
+
Object.freeze({ label: "No UI impact", value: "none" }),
|
|
125
|
+
Object.freeze({ label: "Possible UI impact", value: "possible" }),
|
|
126
|
+
Object.freeze({ label: "Definite UI impact", value: "definite" }),
|
|
127
|
+
Object.freeze({ label: "Unknown", value: "unknown" })
|
|
128
|
+
]),
|
|
129
|
+
required: true
|
|
130
|
+
});
|
|
28
131
|
const USER_CHECK_INPUT = Object.freeze({
|
|
29
132
|
label: "User check result",
|
|
30
133
|
name: "userCheck",
|
|
@@ -35,19 +138,50 @@ const USER_CHECK_INPUT = Object.freeze({
|
|
|
35
138
|
required: true,
|
|
36
139
|
type: "choice"
|
|
37
140
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
function codexHandoff(expectedOutput) {
|
|
141
|
+
function codexHandoff(expectedOutput, {
|
|
142
|
+
autoInject = false,
|
|
143
|
+
promptActionLabel = ""
|
|
144
|
+
} = {}) {
|
|
145
|
+
const expectedOutputs = Object.freeze(Array.isArray(expectedOutput) ? [...expectedOutput] : [expectedOutput]);
|
|
44
146
|
return Object.freeze({
|
|
45
|
-
|
|
147
|
+
...(autoInject ? { autoInject: true } : {}),
|
|
148
|
+
expectedOutput: expectedOutputs[expectedOutputs.length - 1] || null,
|
|
149
|
+
expectedOutputs,
|
|
46
150
|
mode: "inject_prompt",
|
|
47
|
-
promptField: "prompt"
|
|
151
|
+
promptField: "prompt",
|
|
152
|
+
...(promptActionLabel ? { promptActionLabel } : {})
|
|
48
153
|
});
|
|
49
154
|
}
|
|
50
155
|
|
|
156
|
+
const PLAN_EXECUTION_CODEX_HANDOFF = codexHandoff([], {
|
|
157
|
+
autoInject: true,
|
|
158
|
+
promptActionLabel: "Get Codex to execute plan"
|
|
159
|
+
});
|
|
160
|
+
const ISSUE_DETAILS_CODEX_HANDOFF = codexHandoff([
|
|
161
|
+
ISSUE_CATEGORY_OUTPUT,
|
|
162
|
+
UI_IMPACT_OUTPUT,
|
|
163
|
+
ISSUE_DETAILS_OUTPUT
|
|
164
|
+
], {
|
|
165
|
+
autoInject: true,
|
|
166
|
+
promptActionLabel: "Start details conversation"
|
|
167
|
+
});
|
|
168
|
+
const REVIEW_EXECUTION_CODEX_HANDOFF = codexHandoff([], {
|
|
169
|
+
autoInject: true,
|
|
170
|
+
promptActionLabel: "Run deslop"
|
|
171
|
+
});
|
|
172
|
+
const DEEP_UI_CHECK_CODEX_HANDOFF = codexHandoff([], {
|
|
173
|
+
autoInject: true,
|
|
174
|
+
promptActionLabel: "Run Deep UI check"
|
|
175
|
+
});
|
|
176
|
+
const AUTOMATED_CHECK_REPAIR_CODEX_HANDOFF = codexHandoff([], {
|
|
177
|
+
autoInject: true,
|
|
178
|
+
promptActionLabel: "Run automated checks"
|
|
179
|
+
});
|
|
180
|
+
const BLUEPRINT_CODEX_HANDOFF = codexHandoff([], {
|
|
181
|
+
autoInject: true,
|
|
182
|
+
promptActionLabel: "Update blueprint"
|
|
183
|
+
});
|
|
184
|
+
|
|
51
185
|
function defineStep({
|
|
52
186
|
buttonLabel,
|
|
53
187
|
codex = undefined,
|
|
@@ -56,39 +190,54 @@ function defineStep({
|
|
|
56
190
|
input = INPUT_NONE,
|
|
57
191
|
kind = "automatic",
|
|
58
192
|
label,
|
|
59
|
-
nextCommandTemplate =
|
|
60
|
-
preconditions = []
|
|
193
|
+
nextCommandTemplate = DEFAULT_NEXT_COMMAND_TEMPLATE,
|
|
194
|
+
preconditions = [],
|
|
195
|
+
requiresExplicitRun = false,
|
|
196
|
+
utilityActions = [],
|
|
197
|
+
displayGroupId = "",
|
|
198
|
+
displayGroupLabel = ""
|
|
61
199
|
}) {
|
|
62
200
|
return Object.freeze({
|
|
63
201
|
buttonLabel,
|
|
64
202
|
codex,
|
|
65
203
|
description,
|
|
204
|
+
displayGroupId,
|
|
205
|
+
displayGroupLabel,
|
|
66
206
|
id,
|
|
67
207
|
input,
|
|
68
208
|
kind,
|
|
69
209
|
label,
|
|
70
210
|
nextCommandTemplate,
|
|
71
|
-
preconditions: Object.freeze([...preconditions])
|
|
211
|
+
preconditions: Object.freeze([...preconditions]),
|
|
212
|
+
requiresExplicitRun,
|
|
213
|
+
utilityActions: Object.freeze([...utilityActions])
|
|
72
214
|
});
|
|
73
215
|
}
|
|
74
216
|
|
|
75
217
|
const STEP_DEFINITIONS = Object.freeze([
|
|
76
218
|
defineStep({
|
|
77
219
|
buttonLabel: "Create session",
|
|
78
|
-
description: "
|
|
220
|
+
description: "JSKIT creates the filesystem-backed session record and initial receipt.",
|
|
79
221
|
id: "session_created",
|
|
80
222
|
label: "Session created"
|
|
81
223
|
}),
|
|
82
224
|
defineStep({
|
|
83
225
|
buttonLabel: "Create worktree",
|
|
84
|
-
description: "
|
|
226
|
+
description: "JSKIT creates the isolated Git branch and session worktree where Codex will work.",
|
|
85
227
|
id: "worktree_created",
|
|
86
228
|
label: "Worktree created",
|
|
87
229
|
preconditions: ["session_exists", "git_repository", "git_current_branch"]
|
|
88
230
|
}),
|
|
89
231
|
defineStep({
|
|
90
|
-
buttonLabel: "
|
|
91
|
-
description: "
|
|
232
|
+
buttonLabel: "Install dependencies",
|
|
233
|
+
description: "JSKIT installs Node dependencies inside the session worktree before Codex starts.",
|
|
234
|
+
id: "dependencies_installed",
|
|
235
|
+
label: "Dependencies installed",
|
|
236
|
+
preconditions: ["session_exists", "worktree_exists"]
|
|
237
|
+
}),
|
|
238
|
+
defineStep({
|
|
239
|
+
buttonLabel: "Set initial prompt",
|
|
240
|
+
description: "User describes the requested change; JSKIT records it and prepares the Codex issue-drafting prompt.",
|
|
92
241
|
id: "issue_prompt_rendered",
|
|
93
242
|
input: Object.freeze({
|
|
94
243
|
label: "What should change?",
|
|
@@ -99,175 +248,169 @@ const STEP_DEFINITIONS = Object.freeze([
|
|
|
99
248
|
type: "text"
|
|
100
249
|
}),
|
|
101
250
|
kind: "human_input",
|
|
102
|
-
label: "
|
|
103
|
-
nextCommandTemplate:
|
|
104
|
-
preconditions: ["session_exists"]
|
|
251
|
+
label: "Initial issue prompt",
|
|
252
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --prompt "<what should change>"`,
|
|
253
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app"]
|
|
105
254
|
}),
|
|
106
255
|
defineStep({
|
|
107
|
-
buttonLabel: "
|
|
108
|
-
codex: codexHandoff(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
256
|
+
buttonLabel: "Finalise issue",
|
|
257
|
+
codex: codexHandoff([
|
|
258
|
+
ISSUE_TITLE_OUTPUT,
|
|
259
|
+
ISSUE_TEXT_OUTPUT
|
|
260
|
+
], {
|
|
261
|
+
autoInject: true,
|
|
262
|
+
promptActionLabel: "Get Codex to create issue text"
|
|
263
|
+
}),
|
|
264
|
+
description: "Codex drafts the issue title and body; user reviews or edits them; JSKIT saves the approved draft.",
|
|
114
265
|
id: "issue_drafted",
|
|
115
|
-
input:
|
|
266
|
+
input: ISSUE_DRAFT_INPUT,
|
|
116
267
|
kind: "codex_output",
|
|
117
268
|
label: "Issue drafted",
|
|
118
|
-
nextCommandTemplate:
|
|
119
|
-
preconditions: ["session_exists"]
|
|
269
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --issue -`,
|
|
270
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app"]
|
|
120
271
|
}),
|
|
121
272
|
defineStep({
|
|
122
|
-
buttonLabel: "Create
|
|
123
|
-
description: "
|
|
273
|
+
buttonLabel: "Create issue",
|
|
274
|
+
description: "JSKIT creates the GitHub issue from the approved draft and records the issue URL.",
|
|
124
275
|
id: "issue_created",
|
|
125
276
|
label: "Issue created",
|
|
126
|
-
preconditions: ["session_exists", "issue_text_exists", "github_auth", "github_origin"]
|
|
277
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_text_exists", "github_auth", "github_origin"],
|
|
278
|
+
requiresExplicitRun: false
|
|
127
279
|
}),
|
|
128
280
|
defineStep({
|
|
129
|
-
buttonLabel: "
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
281
|
+
buttonLabel: "Save issue details",
|
|
282
|
+
codex: ISSUE_DETAILS_CODEX_HANDOFF,
|
|
283
|
+
description: "Codex finalises with user issue details and classification; user reviews or edits final outcome; JSKIT saves the confirmed details.",
|
|
284
|
+
displayGroupId: "issue_details",
|
|
285
|
+
displayGroupLabel: "Get issue details",
|
|
286
|
+
id: "issue_details_gathered",
|
|
287
|
+
input: ISSUE_DETAILS_INPUT,
|
|
288
|
+
kind: "codex_output",
|
|
289
|
+
label: "Issue details gathered",
|
|
290
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --issue-details -`,
|
|
291
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_text_exists", "issue_url_exists"]
|
|
135
292
|
}),
|
|
136
293
|
defineStep({
|
|
137
|
-
buttonLabel: "
|
|
138
|
-
codex: codexHandoff(
|
|
139
|
-
|
|
140
|
-
|
|
294
|
+
buttonLabel: "Save plan",
|
|
295
|
+
codex: codexHandoff(PLAN_OUTPUT, {
|
|
296
|
+
autoInject: true,
|
|
297
|
+
promptActionLabel: "Get Codex to create plan"
|
|
298
|
+
}),
|
|
299
|
+
description: "Codex writes an implementation plan for the active cycle; cycle 001 plans from the issue, later cycles plan from user rework notes.",
|
|
300
|
+
id: "plan_made",
|
|
301
|
+
input: PLAN_INPUT,
|
|
141
302
|
kind: "codex_output",
|
|
142
|
-
label: "
|
|
143
|
-
|
|
303
|
+
label: "Plan made",
|
|
304
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --plan -`,
|
|
305
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_text_exists", "issue_url_exists", "issue_details_exists", "issue_metadata_exists", "active_cycle_exists"]
|
|
144
306
|
}),
|
|
145
307
|
defineStep({
|
|
146
|
-
buttonLabel: "
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
308
|
+
buttonLabel: "Get Codex to execute plan",
|
|
309
|
+
codex: PLAN_EXECUTION_CODEX_HANDOFF,
|
|
310
|
+
description: "JSKIT sends the active cycle plan to Codex; Codex implements it; Studio advances when Codex finishes.",
|
|
311
|
+
id: "plan_executed",
|
|
312
|
+
kind: "codex_prompt",
|
|
313
|
+
label: "Plan executed",
|
|
314
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_text_exists", "issue_url_exists", "issue_details_exists", "issue_metadata_exists", "active_cycle_exists", "plan_text_exists"]
|
|
151
315
|
}),
|
|
152
316
|
defineStep({
|
|
153
|
-
buttonLabel: "
|
|
154
|
-
|
|
155
|
-
|
|
317
|
+
buttonLabel: "Run Deep UI check",
|
|
318
|
+
codex: DEEP_UI_CHECK_CODEX_HANDOFF,
|
|
319
|
+
description: "JSKIT asks Codex for a focused UI quality pass when the issue affects UI, or records a skip receipt when it does not.",
|
|
320
|
+
id: "deep_ui_check_run",
|
|
156
321
|
kind: "codex_prompt",
|
|
157
|
-
label: "
|
|
158
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
322
|
+
label: "Deep UI check run",
|
|
323
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists"]
|
|
159
324
|
}),
|
|
160
325
|
defineStep({
|
|
161
|
-
buttonLabel: "
|
|
162
|
-
codex:
|
|
163
|
-
description: "
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
326
|
+
buttonLabel: "Run deslop",
|
|
327
|
+
codex: REVIEW_EXECUTION_CODEX_HANDOFF,
|
|
328
|
+
description: "JSKIT sends the current implementation to Codex for a review/deslop pass; Codex reports findings and applies the selected cleanup.",
|
|
329
|
+
displayGroupId: "review_deslop",
|
|
330
|
+
displayGroupLabel: "Review/deslop",
|
|
331
|
+
id: "review_prompt_rendered",
|
|
332
|
+
kind: "codex_prompt",
|
|
333
|
+
label: "Review/deslop",
|
|
334
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "deep_ui_check_satisfied"]
|
|
168
335
|
}),
|
|
169
336
|
defineStep({
|
|
170
|
-
buttonLabel: "
|
|
171
|
-
description: "
|
|
172
|
-
|
|
173
|
-
|
|
337
|
+
buttonLabel: "I am done",
|
|
338
|
+
description: "User confirms the review/deslop loop is done; JSKIT records the loop result without committing yet.",
|
|
339
|
+
displayGroupId: "review_deslop",
|
|
340
|
+
displayGroupLabel: "Review/deslop",
|
|
341
|
+
id: "review_changes_accepted",
|
|
174
342
|
kind: "user_check",
|
|
175
|
-
label: "
|
|
176
|
-
nextCommandTemplate:
|
|
177
|
-
preconditions: ["session_exists"]
|
|
343
|
+
label: "Review/deslop",
|
|
344
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --review-findings-remaining false`,
|
|
345
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "deep_ui_check_satisfied"]
|
|
178
346
|
}),
|
|
179
347
|
defineStep({
|
|
180
|
-
buttonLabel: "
|
|
181
|
-
|
|
182
|
-
|
|
348
|
+
buttonLabel: "Run automated checks",
|
|
349
|
+
codex: AUTOMATED_CHECK_REPAIR_CODEX_HANDOFF,
|
|
350
|
+
description: "JSKIT asks Codex to run automated checks in the worktree, fix failures, and report the final result.",
|
|
351
|
+
id: "automated_checks_run",
|
|
183
352
|
kind: "codex_prompt",
|
|
184
|
-
label: "
|
|
185
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
186
|
-
}),
|
|
187
|
-
defineStep({
|
|
188
|
-
buttonLabel: "Detect review changes 2",
|
|
189
|
-
codex: codexHandoff(CODEX_WORKTREE_OUTPUT),
|
|
190
|
-
description: "Commit any changes Codex made after the second review pass.",
|
|
191
|
-
id: "followup_review_changes_detected",
|
|
192
|
-
kind: "codex_output",
|
|
193
|
-
label: "Review changes detected 2",
|
|
194
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
353
|
+
label: "Automated checks",
|
|
354
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "deep_ui_check_satisfied"]
|
|
195
355
|
}),
|
|
196
356
|
defineStep({
|
|
197
|
-
buttonLabel: "Save user check
|
|
198
|
-
description: "
|
|
199
|
-
id: "
|
|
357
|
+
buttonLabel: "Save user check",
|
|
358
|
+
description: "User manually checks the result; JSKIT records pass or collects rework notes for another plan cycle.",
|
|
359
|
+
id: "user_check_completed",
|
|
200
360
|
input: USER_CHECK_INPUT,
|
|
201
361
|
kind: "user_check",
|
|
202
|
-
label: "User check
|
|
203
|
-
nextCommandTemplate:
|
|
204
|
-
preconditions: ["session_exists"]
|
|
362
|
+
label: "User check",
|
|
363
|
+
nextCommandTemplate: `${JSKIT_CLI_SHELL_COMMAND} session {{session_id}} step --user-check passed`,
|
|
364
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied"]
|
|
205
365
|
}),
|
|
206
366
|
defineStep({
|
|
207
|
-
buttonLabel: "
|
|
208
|
-
description: "
|
|
209
|
-
id: "
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
213
|
-
}),
|
|
214
|
-
defineStep({
|
|
215
|
-
buttonLabel: "Detect final review changes",
|
|
216
|
-
codex: codexHandoff(CODEX_WORKTREE_OUTPUT),
|
|
217
|
-
description: "Commit any changes Codex made after the final review pass.",
|
|
218
|
-
id: "final_review_changes_detected",
|
|
219
|
-
kind: "codex_output",
|
|
220
|
-
label: "Review changes detected 3",
|
|
221
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
367
|
+
buttonLabel: "Commit accepted changes",
|
|
368
|
+
description: "JSKIT commits the user-accepted session changes in the session worktree.",
|
|
369
|
+
id: "changes_committed",
|
|
370
|
+
label: "Changes committed",
|
|
371
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "issue_url_exists", "github_auth", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied", "active_cycle_user_check_passed"]
|
|
222
372
|
}),
|
|
223
373
|
defineStep({
|
|
224
|
-
buttonLabel: "
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
kind: "
|
|
229
|
-
label: "
|
|
230
|
-
|
|
231
|
-
preconditions: ["session_exists"]
|
|
374
|
+
buttonLabel: "Update blueprint",
|
|
375
|
+
codex: BLUEPRINT_CODEX_HANDOFF,
|
|
376
|
+
description: "JSKIT asks Codex to update durable app memory from the accepted work; Codex edits .jskit/APP_BLUEPRINT.md; JSKIT records and commits the update.",
|
|
377
|
+
id: "blueprint_updated",
|
|
378
|
+
kind: "codex_prompt",
|
|
379
|
+
label: "Blueprint updated",
|
|
380
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied", "active_cycle_user_check_passed", "accepted_changes_committed"]
|
|
232
381
|
}),
|
|
233
382
|
defineStep({
|
|
234
383
|
buttonLabel: "Run verification",
|
|
235
|
-
description: "
|
|
384
|
+
description: "JSKIT runs the final project verification command in the session worktree and records the result.",
|
|
236
385
|
id: "doctor_run",
|
|
237
|
-
label: "
|
|
238
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
386
|
+
label: "Verification run",
|
|
387
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied", "active_cycle_user_check_passed", "accepted_changes_committed", "blueprint_update_satisfied"]
|
|
239
388
|
}),
|
|
240
389
|
defineStep({
|
|
241
|
-
buttonLabel: "
|
|
242
|
-
description: "
|
|
243
|
-
id: "
|
|
244
|
-
label: "
|
|
245
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
390
|
+
buttonLabel: "Create final report",
|
|
391
|
+
description: "JSKIT creates the deterministic final session report and comments it on the GitHub issue.",
|
|
392
|
+
id: "final_report_created",
|
|
393
|
+
label: "Final report created",
|
|
394
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied", "active_cycle_user_check_passed", "accepted_changes_committed", "blueprint_update_satisfied"]
|
|
246
395
|
}),
|
|
247
396
|
defineStep({
|
|
248
|
-
buttonLabel: "
|
|
249
|
-
description: "
|
|
397
|
+
buttonLabel: "Push branch and create PR",
|
|
398
|
+
description: "JSKIT pushes the session branch to origin, creates or reuses the GitHub pull request, and records the PR URL.",
|
|
250
399
|
id: "pr_created",
|
|
251
|
-
label: "PR created",
|
|
252
|
-
preconditions: ["session_exists", "worktree_exists"]
|
|
400
|
+
label: "Branch pushed, PR created",
|
|
401
|
+
preconditions: ["session_exists", "worktree_exists", "dependencies_installed", "ready_jskit_app", "issue_metadata_exists", "active_cycle_exists", "automated_checks_passed", "deep_ui_check_satisfied", "active_cycle_user_check_passed", "accepted_changes_committed", "blueprint_update_satisfied", "final_report_exists"]
|
|
253
402
|
}),
|
|
254
403
|
defineStep({
|
|
255
404
|
buttonLabel: "Merge PR",
|
|
256
|
-
description: "
|
|
257
|
-
id: "
|
|
258
|
-
label: "PR
|
|
259
|
-
preconditions: ["session_exists", "pr_url_exists"]
|
|
260
|
-
|
|
261
|
-
defineStep({
|
|
262
|
-
buttonLabel: "Remove worktree",
|
|
263
|
-
description: "Remove the session worktree after the PR has merged.",
|
|
264
|
-
id: "worktree_removed",
|
|
265
|
-
label: "Worktree removed",
|
|
266
|
-
preconditions: ["session_exists"]
|
|
405
|
+
description: "User chooses whether JSKIT merges the pull request or finishes without merge; JSKIT then removes the session worktree.",
|
|
406
|
+
id: "pr_finalized",
|
|
407
|
+
label: "PR finalized, worktree removed",
|
|
408
|
+
preconditions: ["session_exists", "pr_url_exists", "worktree_exists"],
|
|
409
|
+
requiresExplicitRun: true
|
|
267
410
|
}),
|
|
268
411
|
defineStep({
|
|
269
412
|
buttonLabel: "Finish session",
|
|
270
|
-
description: "
|
|
413
|
+
description: "JSKIT writes the final receipt and archives the completed session.",
|
|
271
414
|
id: "session_finished",
|
|
272
415
|
label: "Session finished",
|
|
273
416
|
preconditions: ["session_exists"]
|
|
@@ -277,6 +420,15 @@ const STEP_DEFINITIONS = Object.freeze([
|
|
|
277
420
|
const STEP_IDS = Object.freeze(STEP_DEFINITIONS.map((step) => step.id));
|
|
278
421
|
const STEP_LABEL_BY_ID = Object.freeze(Object.fromEntries(STEP_DEFINITIONS.map((step) => [step.id, step.label])));
|
|
279
422
|
const STEP_DEFINITION_BY_ID = Object.freeze(Object.fromEntries(STEP_DEFINITIONS.map((step) => [step.id, step])));
|
|
423
|
+
const CYCLE_STEP_IDS = Object.freeze([
|
|
424
|
+
"plan_made",
|
|
425
|
+
"plan_executed",
|
|
426
|
+
"deep_ui_check_run",
|
|
427
|
+
"review_prompt_rendered",
|
|
428
|
+
"review_changes_accepted",
|
|
429
|
+
"automated_checks_run",
|
|
430
|
+
"user_check_completed"
|
|
431
|
+
]);
|
|
280
432
|
const STEP_PRECONDITION_NAMES = Object.freeze(Object.fromEntries(
|
|
281
433
|
STEP_DEFINITIONS
|
|
282
434
|
.filter((step) => step.id !== "session_created")
|
|
@@ -287,10 +439,21 @@ export {
|
|
|
287
439
|
PROMPT_DIRECTORY,
|
|
288
440
|
SESSION_ID_PATTERN,
|
|
289
441
|
SESSION_STATUS,
|
|
442
|
+
SESSION_WORKFLOW_VERSION,
|
|
443
|
+
REVIEW_PASS_LIMIT,
|
|
444
|
+
CYCLE_STEP_IDS,
|
|
290
445
|
STEP_DEFINITION_BY_ID,
|
|
291
446
|
STEP_DEFINITIONS,
|
|
292
447
|
STEP_IDS,
|
|
293
448
|
STEP_LABEL_BY_ID,
|
|
294
449
|
STEP_PRECONDITION_NAMES,
|
|
450
|
+
ISSUE_DETAILS_CODEX_HANDOFF,
|
|
451
|
+
PLAN_EXECUTION_CODEX_HANDOFF,
|
|
452
|
+
REVIEW_EXECUTION_CODEX_HANDOFF,
|
|
453
|
+
DEEP_UI_CHECK_CODEX_HANDOFF,
|
|
454
|
+
AUTOMATED_CHECK_REPAIR_CODEX_HANDOFF,
|
|
455
|
+
BLUEPRINT_CODEX_HANDOFF,
|
|
456
|
+
JSKIT_CLI_SHELL_COMMAND,
|
|
457
|
+
JSKIT_CLI_SHELL_RULE,
|
|
295
458
|
SESSION_STATE_RELATIVE_PATH
|
|
296
459
|
};
|
|
@@ -68,10 +68,9 @@ function resolveSessionPaths({ targetRoot, sessionId = "" } = {}) {
|
|
|
68
68
|
const sessionsRoot = path.join(sessionStateRoot, "active");
|
|
69
69
|
const completedSessionsRoot = path.join(sessionStateRoot, "completed");
|
|
70
70
|
const abandonedSessionsRoot = path.join(sessionStateRoot, "abandoned");
|
|
71
|
-
const worktreesRoot = path.join(sessionStateRoot, "worktrees");
|
|
72
71
|
const normalizedSessionId = sessionId ? normalizeSessionId(sessionId) : "";
|
|
73
72
|
const sessionRoot = normalizedSessionId ? path.join(sessionsRoot, normalizedSessionId) : "";
|
|
74
|
-
const worktree = normalizedSessionId ? path.join(
|
|
73
|
+
const worktree = normalizedSessionId ? path.join(sessionRoot, "worktree") : "";
|
|
75
74
|
const branch = normalizedSessionId ? `jskit-studio/${normalizedSessionId}` : "";
|
|
76
75
|
|
|
77
76
|
return Object.freeze({
|
|
@@ -85,8 +84,7 @@ function resolveSessionPaths({ targetRoot, sessionId = "" } = {}) {
|
|
|
85
84
|
sessionsRoot,
|
|
86
85
|
sessionStateRoot,
|
|
87
86
|
targetRoot: normalizedTargetRoot,
|
|
88
|
-
worktree
|
|
89
|
-
worktreesRoot
|
|
87
|
+
worktree
|
|
90
88
|
});
|
|
91
89
|
}
|
|
92
90
|
|