@cyanautomation/kaseki-agent 1.25.1 → 1.25.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 +92 -41
- package/dist/config/ConfigManager.d.ts +4 -4
- package/dist/github-app-private-key.d.ts +9 -0
- package/dist/github-app-private-key.d.ts.map +1 -0
- package/dist/github-app-private-key.js +98 -0
- package/dist/github-app-private-key.js.map +1 -0
- package/dist/github-app-token.js +13 -2
- package/dist/github-app-token.js.map +1 -1
- package/dist/job-scheduler.d.ts.map +1 -1
- package/dist/job-scheduler.js +13 -4
- package/dist/job-scheduler.js.map +1 -1
- package/dist/kaseki-api-routes.d.ts.map +1 -1
- package/dist/kaseki-api-routes.js +9 -7
- package/dist/kaseki-api-routes.js.map +1 -1
- package/dist/kaseki-api-types.d.ts +6 -3
- package/dist/kaseki-api-types.d.ts.map +1 -1
- package/dist/kaseki-api-types.js +5 -1
- package/dist/kaseki-api-types.js.map +1 -1
- package/dist/openapi-spec-generator.d.ts.map +1 -1
- package/dist/openapi-spec-generator.js +6 -1
- package/dist/openapi-spec-generator.js.map +1 -1
- package/dist/validation-output-filter.js +34 -18
- package/dist/validation-output-filter.js.map +1 -1
- package/kaseki-agent.sh +914 -185
- package/package.json +2 -2
- package/scripts/kaseki-diagnose-github-failure.sh +27 -11
- package/scripts/test-github-app.sh +41 -4
- package/scripts/validate-module-imports.js +1 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Kaseki is a proof-of-concept ephemeral coding-agent runner. Each run is a number
|
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
|
-
###
|
|
7
|
+
### Installation (Recommended)
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# Global install (recommended)
|
|
@@ -21,7 +21,7 @@ kaseki-agent list
|
|
|
21
21
|
kaseki-agent report kaseki-1
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
###
|
|
24
|
+
### Without Global Install
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
npm install @cyanautomation/kaseki-agent
|
|
@@ -29,7 +29,7 @@ npx kaseki-agent setup
|
|
|
29
29
|
npx kaseki-agent run https://github.com/CyanAutomation/crudmapper main
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
###
|
|
32
|
+
### Using Docker ⭐ (Alternative)
|
|
33
33
|
|
|
34
34
|
If you prefer to avoid installing Node.js globally:
|
|
35
35
|
|
|
@@ -62,23 +62,23 @@ Each produces a numbered instance (kaseki-1, kaseki-2, …) with isolated worksp
|
|
|
62
62
|
|
|
63
63
|
## Getting Started
|
|
64
64
|
|
|
65
|
-
###
|
|
65
|
+
### Installation & Setup
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
#### Option A: Global NPM
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
npm install -g @cyanautomation/kaseki-agent
|
|
71
71
|
kaseki-agent setup
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
#### Option B: Local NPM
|
|
75
75
|
|
|
76
76
|
```bash
|
|
77
77
|
npm install @cyanautomation/kaseki-agent
|
|
78
78
|
npx kaseki-agent setup
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
#### Option C: Docker
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
docker run -it \
|
|
@@ -87,13 +87,13 @@ docker run -it \
|
|
|
87
87
|
setup
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
###
|
|
90
|
+
### Verify Installation
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
93
|
kaseki-agent doctor
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
###
|
|
96
|
+
### Configure Authentication
|
|
97
97
|
|
|
98
98
|
Kaseki needs three sets of credentials. Choose your preferred setup method:
|
|
99
99
|
|
|
@@ -134,7 +134,7 @@ See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for setting up the kaseki-api servi
|
|
|
134
134
|
|
|
135
135
|
**👉 Full guide:** [docs/AUTH_SETUP.md](docs/AUTH_SETUP.md)
|
|
136
136
|
|
|
137
|
-
###
|
|
137
|
+
### Run Your First Task
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
# Simple example
|
|
@@ -145,7 +145,7 @@ kaseki-agent run https://github.com/CyanAutomation/crudmapper main \
|
|
|
145
145
|
"Fix the TypeScript errors in src/"
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
###
|
|
148
|
+
### View Results
|
|
149
149
|
|
|
150
150
|
```bash
|
|
151
151
|
# List all instances
|
|
@@ -159,7 +159,7 @@ kaseki-agent report kaseki-1
|
|
|
159
159
|
|
|
160
160
|
## CLI Commands
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
#### `setup` — Interactive Configuration Wizard
|
|
163
163
|
|
|
164
164
|
First-time setup to validate environment and store API credentials securely.
|
|
165
165
|
|
|
@@ -176,7 +176,7 @@ kaseki-agent setup
|
|
|
176
176
|
- Saves configuration (project-local or user-global)
|
|
177
177
|
- Runs doctor checks to verify everything works
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
#### `run` — Execute Agent on Repository
|
|
180
180
|
|
|
181
181
|
```bash
|
|
182
182
|
kaseki-agent run <REPO_URL> [GIT_REF] [TASK_PROMPT]
|
|
@@ -205,7 +205,7 @@ kaseki-agent run https://github.com/CyanAutomation/crudmapper main \
|
|
|
205
205
|
5. Stream agent output in real-time
|
|
206
206
|
6. Collect results and generate report
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
#### `doctor` — Health Check & Validation
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
211
|
kaseki-agent doctor [--json] [--fix]
|
|
@@ -226,7 +226,7 @@ kaseki-agent doctor [--json] [--fix]
|
|
|
226
226
|
- `--json` — JSON output (useful for scripts)
|
|
227
227
|
- `--fix` — Attempt auto-remediation (pull image, show install hints)
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
#### `list` — Show All Instances
|
|
230
230
|
|
|
231
231
|
```bash
|
|
232
232
|
kaseki-agent list [--status STATE]
|
|
@@ -247,7 +247,7 @@ kaseki-agent list --status running
|
|
|
247
247
|
- Creation date
|
|
248
248
|
- Execution duration
|
|
249
249
|
|
|
250
|
-
|
|
250
|
+
#### `report` — View Instance Results
|
|
251
251
|
|
|
252
252
|
```bash
|
|
253
253
|
kaseki-agent report <INSTANCE_ID>
|
|
@@ -260,7 +260,7 @@ kaseki-agent report <INSTANCE_ID>
|
|
|
260
260
|
- Final status and exit code
|
|
261
261
|
- Detailed summary (if available)
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
#### `config` — Manage Configuration
|
|
264
264
|
|
|
265
265
|
```bash
|
|
266
266
|
kaseki-agent config <SUBCOMMAND> [OPTIONS]
|
|
@@ -285,7 +285,7 @@ kaseki-agent config show
|
|
|
285
285
|
kaseki-agent config locations
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
-
|
|
288
|
+
#### `secrets` — Manage Credentials
|
|
289
289
|
|
|
290
290
|
```bash
|
|
291
291
|
kaseki-agent secrets <SUBCOMMAND>
|
|
@@ -318,7 +318,7 @@ kaseki-agent secrets list
|
|
|
318
318
|
- Linux: Uses `pass` (password-store) keyring
|
|
319
319
|
- Headless: Falls back to `~/.kaseki/secrets/` (0600 permissions)
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
#### `serve` — Start REST API Service
|
|
322
322
|
|
|
323
323
|
```bash
|
|
324
324
|
kaseki-agent serve [--port PORT]
|
|
@@ -373,6 +373,8 @@ Configuration is loaded from (in order of precedence):
|
|
|
373
373
|
4. **Environment variables** (`KASEKI_*`, `OPENROUTER_*`, `GITHUB_*`)
|
|
374
374
|
5. **Built-in defaults**
|
|
375
375
|
|
|
376
|
+
### Example Configuration
|
|
377
|
+
|
|
376
378
|
**Example `kaseki-agent.json`:**
|
|
377
379
|
|
|
378
380
|
```json
|
|
@@ -391,7 +393,7 @@ Configuration is loaded from (in order of precedence):
|
|
|
391
393
|
}
|
|
392
394
|
```
|
|
393
395
|
|
|
394
|
-
|
|
396
|
+
### Common Environment Variables
|
|
395
397
|
|
|
396
398
|
```bash
|
|
397
399
|
# Required
|
|
@@ -401,7 +403,10 @@ OPENROUTER_API_KEY_FILE=~/.kaseki/secrets/openrouter_api_key
|
|
|
401
403
|
KASEKI_ROOT=/agents # Base directory
|
|
402
404
|
KASEKI_MODEL=openrouter/free # AI model
|
|
403
405
|
KASEKI_AGENT_TIMEOUT_SECONDS=1200 # Timeout
|
|
404
|
-
|
|
406
|
+
KASEKI_PRE_AGENT_VALIDATION=1 # Validate baseline before Pi
|
|
407
|
+
KASEKI_PRE_AGENT_VALIDATION_COMMANDS="npm run check;npm run test;npm run build"
|
|
408
|
+
KASEKI_VALIDATION_COMMANDS="npm run check;npm run test;npm run build" # Validate final diff after Pi
|
|
409
|
+
KASEKI_STARTUP_CHECK_MODE=boot # boot or baseline-validation for dry-run startup checks
|
|
405
410
|
```
|
|
406
411
|
|
|
407
412
|
---
|
|
@@ -410,7 +415,7 @@ KASEKI_VALIDATION_COMMANDS="npm run check;npm run test;npm run build"
|
|
|
410
415
|
|
|
411
416
|
### Deployment Patterns
|
|
412
417
|
|
|
413
|
-
|
|
418
|
+
#### CLI (Direct Execution)
|
|
414
419
|
|
|
415
420
|
```bash
|
|
416
421
|
kaseki-agent run <repo> <ref>
|
|
@@ -420,7 +425,7 @@ kaseki-agent run <repo> <ref>
|
|
|
420
425
|
- Immediate results
|
|
421
426
|
- Best for: CI/CD, direct usage
|
|
422
427
|
|
|
423
|
-
|
|
428
|
+
#### REST API (Distributed)
|
|
424
429
|
|
|
425
430
|
```bash
|
|
426
431
|
kaseki-agent serve --port 8080
|
|
@@ -431,7 +436,7 @@ kaseki-agent serve --port 8080
|
|
|
431
436
|
- Async execution
|
|
432
437
|
- Best for: Controllers, distributed systems
|
|
433
438
|
|
|
434
|
-
|
|
439
|
+
#### Docker (Self-Contained)
|
|
435
440
|
|
|
436
441
|
```bash
|
|
437
442
|
docker run docker.io/cyanautomation/kaseki-agent:latest run <repo> <ref>
|
|
@@ -441,6 +446,8 @@ docker run docker.io/cyanautomation/kaseki-agent:latest run <repo> <ref>
|
|
|
441
446
|
- Full isolation
|
|
442
447
|
- Best for: Clean environments, CI/CD containers
|
|
443
448
|
|
|
449
|
+
### Host and Container Layers
|
|
450
|
+
|
|
444
451
|
**Host layer** — Management and orchestration:
|
|
445
452
|
|
|
446
453
|
- `run-kaseki.sh` — Direct runner (creates workspace, launches container, cleans up)
|
|
@@ -449,13 +456,21 @@ docker run docker.io/cyanautomation/kaseki-agent:latest run <repo> <ref>
|
|
|
449
456
|
|
|
450
457
|
**Container layer** — Agent execution:
|
|
451
458
|
|
|
452
|
-
- `kaseki-agent.sh` — Inside the container (clones repo, installs deps, invokes Pi,
|
|
459
|
+
- `kaseki-agent.sh` — Inside the container (clones repo, installs deps, runs pre-agent validation, invokes Pi, runs post-agent validation, stores results)
|
|
453
460
|
- `entrypoint.sh` — Container startup orchestrator
|
|
454
461
|
|
|
462
|
+
### Validation Lifecycle
|
|
463
|
+
|
|
464
|
+
1. Clone the target repo/ref and install dependencies.
|
|
465
|
+
2. Run **pre-agent validation** when `KASEKI_PRE_AGENT_VALIDATION=1` (default). These commands default to `KASEKI_VALIDATION_COMMANDS` through `KASEKI_PRE_AGENT_VALIDATION_COMMANDS` and execute before Pi so Kaseki can detect an already-failing baseline. Inspect `/agents/kaseki-results/kaseki-N/pre-validation.log`, `/agents/kaseki-results/kaseki-N/pre-validation-raw.log`, `/agents/kaseki-results/kaseki-N/pre-validation-env.log`, and `/agents/kaseki-results/kaseki-N/pre-validation-timings.tsv`.
|
|
466
|
+
3. Invoke Pi only if the baseline validation succeeds (or pre-agent validation is disabled).
|
|
467
|
+
4. Restore disallowed changes, run quality gates, then run **post-agent validation** with `KASEKI_VALIDATION_COMMANDS` against the final diff. Inspect `/agents/kaseki-results/kaseki-N/validation.log`, `/agents/kaseki-results/kaseki-N/validation-raw.log`, `/agents/kaseki-results/kaseki-N/validation-env.log`, and `/agents/kaseki-results/kaseki-N/validation-timings.tsv`.
|
|
468
|
+
5. Record phase exit codes and failure reasons in `/agents/kaseki-results/kaseki-N/metadata.json`; `stage-timings.tsv` shows whether the failing phase was `pre-agent validation` or `validation`.
|
|
469
|
+
|
|
455
470
|
> **Important:** `kaseki-agent.sh` runs from the Docker image (`/usr/local/bin/kaseki-agent`) and is **not** host-mounted during runs.
|
|
456
471
|
> For Direct CLI mode, the host needs `run-kaseki.sh` (plus `scripts/kaseki-preflight.sh`) and Docker access; the agent script itself stays inside the image.
|
|
457
472
|
|
|
458
|
-
|
|
473
|
+
### Supporting Utilities (Node.js)
|
|
459
474
|
|
|
460
475
|
- `pi-event-filter.js` — Filters raw Pi JSONL, strips thinking blocks, emits `pi-events.jsonl` + `pi-summary.json`
|
|
461
476
|
- `kaseki-report.js` — Reads a results directory and prints diagnostic report
|
|
@@ -463,7 +478,7 @@ docker run docker.io/cyanautomation/kaseki-agent:latest run <repo> <ref>
|
|
|
463
478
|
- `kaseki-api-service.js` — REST API service for remote runs
|
|
464
479
|
- `kaseki-api-client.ts` — TypeScript client for integration
|
|
465
480
|
|
|
466
|
-
|
|
481
|
+
### Directory Layout at Runtime
|
|
467
482
|
|
|
468
483
|
```
|
|
469
484
|
/agents/kaseki-template/ # Dockerfile, scripts (this repo)
|
|
@@ -478,7 +493,7 @@ docker run docker.io/cyanautomation/kaseki-agent:latest run <repo> <ref>
|
|
|
478
493
|
|
|
479
494
|
## Deployment Modes
|
|
480
495
|
|
|
481
|
-
###
|
|
496
|
+
### Direct CLI (run-kaseki.sh)
|
|
482
497
|
|
|
483
498
|
Simplest single-run invocation on a host:
|
|
484
499
|
|
|
@@ -498,7 +513,7 @@ OPENROUTER_API_KEY_FILE=~/secrets/openrouter_api_key \
|
|
|
498
513
|
|
|
499
514
|
---
|
|
500
515
|
|
|
501
|
-
###
|
|
516
|
+
### Remote Activation (kaseki-activate.sh)
|
|
502
517
|
|
|
503
518
|
For SSH/controller-driven setup and execution. Used by OpenClaw and similar orchestrators.
|
|
504
519
|
|
|
@@ -564,7 +579,7 @@ Returns newline-delimited JSON for each major step.
|
|
|
564
579
|
|
|
565
580
|
---
|
|
566
581
|
|
|
567
|
-
###
|
|
582
|
+
### REST API Service (kaseki-api)
|
|
568
583
|
|
|
569
584
|
Long-running async orchestration service. Ideal for:
|
|
570
585
|
|
|
@@ -1174,6 +1189,28 @@ container environment.
|
|
|
1174
1189
|
|
|
1175
1190
|
3. Install the app on the target repository
|
|
1176
1191
|
|
|
1192
|
+
### Single-line/text PEM private keys
|
|
1193
|
+
|
|
1194
|
+
The preferred approach is to paste the GitHub App private key text into a
|
|
1195
|
+
secret file, then reference that file with `GITHUB_APP_PRIVATE_KEY_FILE`. For
|
|
1196
|
+
example, store the value at `/agents/secrets/github_app_private_key` for
|
|
1197
|
+
container or service deployments, or at `~/secrets/github_app_private_key` for
|
|
1198
|
+
local CLI runs.
|
|
1199
|
+
|
|
1200
|
+
Kaseki normalizes the private key after reading it, so the file may contain the
|
|
1201
|
+
original multi-line PEM, a PEM where newlines are escaped as `\n`, a base64-
|
|
1202
|
+
encoded PEM, or a single-line PEM where spaces are used in place of PEM
|
|
1203
|
+
newlines.
|
|
1204
|
+
|
|
1205
|
+
`GITHUB_APP_PRIVATE_KEY` is only for local `run-kaseki.sh` experiments. Config
|
|
1206
|
+
and API service flows may reject inline private keys because they enforce
|
|
1207
|
+
file-based secrets; use `GITHUB_APP_PRIVATE_KEY_FILE` for those flows.
|
|
1208
|
+
|
|
1209
|
+
> **Security warning:** Never paste real private keys into tickets, prompts,
|
|
1210
|
+
> logs, `.env` files, or source control. If a GitHub App private key is exposed,
|
|
1211
|
+
> regenerate the private key in the GitHub App settings and replace the secret
|
|
1212
|
+
> file everywhere it is used.
|
|
1213
|
+
|
|
1177
1214
|
### Setup
|
|
1178
1215
|
|
|
1179
1216
|
```bash
|
|
@@ -1208,10 +1245,12 @@ volumes:
|
|
|
1208
1245
|
- /agents:/agents:rw
|
|
1209
1246
|
```
|
|
1210
1247
|
|
|
1211
|
-
`GITHUB_APP_PRIVATE_KEY` is still accepted as a fallback for local
|
|
1212
|
-
including escaped `\n
|
|
1213
|
-
|
|
1214
|
-
|
|
1248
|
+
`GITHUB_APP_PRIVATE_KEY` is still accepted as a fallback for local
|
|
1249
|
+
`run-kaseki.sh` experiments, including escaped `\n`, base64 PEM, or
|
|
1250
|
+
single-line PEM values after normalization. Avoid inline private keys for shared
|
|
1251
|
+
hosts: environment variables are easier to leak through process inspection,
|
|
1252
|
+
logs, and orchestration UIs, and config/API service flows may reject inline
|
|
1253
|
+
secrets in favor of file-based secret paths.
|
|
1215
1254
|
|
|
1216
1255
|
### Behavior
|
|
1217
1256
|
|
|
@@ -1220,15 +1259,20 @@ When credentials are configured and publishing is enabled:
|
|
|
1220
1259
|
1. After validation passes and diff is non-empty, Kaseki generates a GitHub App installation token
|
|
1221
1260
|
2. Creates a feature branch `kaseki/<instance-name>`
|
|
1222
1261
|
3. Commits and pushes changes to remote
|
|
1223
|
-
4. Creates a draft PR against the target branch when `KASEKI_PUBLISH_MODE=draft_pr` or API `publishMode` is `draft_pr
|
|
1262
|
+
4. Creates a draft PR against the target branch when `KASEKI_PUBLISH_MODE=draft_pr` or API `publishMode` is `draft_pr`; `auto` can also create a draft PR when worker credentials are available, with:
|
|
1224
1263
|
- Title: `Kaseki: <instance-name>`
|
|
1225
1264
|
- Body: Model, duration, validation result, quality checks
|
|
1226
1265
|
- Draft: `true` for safety; review before merging
|
|
1227
1266
|
|
|
1228
|
-
Publishing modes are `none`, `branch`, and `draft_pr`. Controller
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
for
|
|
1267
|
+
Publishing modes are `auto`, `none`, `branch`, and `draft_pr`. Controller
|
|
1268
|
+
requests default omitted `publishMode` to `draft_pr`, so the normal controller
|
|
1269
|
+
path pushes a branch and opens a draft pull request after validation. Explicit
|
|
1270
|
+
API `publishMode: "auto"` is accepted for graceful worker auto publishing: the
|
|
1271
|
+
worker publishes when credentials are available and skips GitHub operations when
|
|
1272
|
+
they are not. Requests that resolve to `branch` or `draft_pr` fail before
|
|
1273
|
+
queueing unless GitHub App credentials are readable, so orchestrators can surface
|
|
1274
|
+
a clear setup error instead of waiting for a run that cannot publish. Set
|
|
1275
|
+
`publishMode` to `none` to opt out of GitHub publishing for a specific API run.
|
|
1232
1276
|
|
|
1233
1277
|
### Result Artifacts
|
|
1234
1278
|
|
|
@@ -1259,13 +1303,18 @@ for a run that cannot publish.
|
|
|
1259
1303
|
| `KASEKI_AGENT_TIMEOUT_SECONDS` | 1200 | Agent timeout (20 min) |
|
|
1260
1304
|
| `TASK_PROMPT` | *(code fix task)* | Agent instructions |
|
|
1261
1305
|
| `KASEKI_TASK_MODE` | patch | `patch` (require diff) or `inspect` (no diff) |
|
|
1262
|
-
| `KASEKI_PUBLISH_MODE` | auto | `none`, `branch`, or `draft_pr`; API requests
|
|
1306
|
+
| `KASEKI_PUBLISH_MODE` | auto | `auto`, `none`, `branch`, or `draft_pr`; controller API requests default omitted `publishMode` to `draft_pr`, while explicit API `publishMode: "auto"` passes graceful auto publishing to workers |
|
|
1307
|
+
| `KASEKI_STARTUP_CHECK_MODE` | boot | Dry-run startup check depth: `boot` or `baseline-validation` |
|
|
1263
1308
|
|
|
1264
1309
|
### Validation and Quality Gates
|
|
1265
1310
|
|
|
1266
1311
|
| Variable | Default | Notes |
|
|
1267
1312
|
|---|---|---|
|
|
1268
|
-
| `
|
|
1313
|
+
| `KASEKI_PRE_AGENT_VALIDATION` | `1` | Run validation before Pi to detect a failing baseline repo/ref. Set to `0` only when you intentionally want to skip baseline validation. |
|
|
1314
|
+
| `KASEKI_PRE_AGENT_VALIDATION_COMMANDS` | same as `KASEKI_VALIDATION_COMMANDS` | Semicolon-separated pre-agent validation commands. Logs: `pre-validation.log`, `pre-validation-raw.log`, `pre-validation-env.log`, `pre-validation-timings.tsv`. |
|
|
1315
|
+
| `KASEKI_VALIDATION_COMMANDS` | `npm run check;npm run test;npm run build` | Semicolon-separated post-agent validation commands for the final diff; set to `none` or empty to skip post-agent validation. Missing npm scripts are skipped with a warning (non-fatal). Logs: `validation.log`, `validation-raw.log`, `validation-env.log`, `validation-timings.tsv`. |
|
|
1316
|
+
| `KASEKI_STARTUP_CHECK_MODE` | `boot` | For `KASEKI_DRY_RUN=1`, `boot` performs a container smoke test through `/bin/bash`; `baseline-validation` runs `/usr/local/bin/kaseki-agent` to clone, install dependencies, run pre-agent validation, and skip Pi. |
|
|
1317
|
+
| `KASEKI_BASELINE_VALIDATION_DRY_RUN` | `0` | Internal/API switch set with `baseline-validation` so pre-agent validation runs even though Pi remains disabled. |
|
|
1269
1318
|
| `KASEKI_CHANGED_FILES_ALLOWLIST` | `src/lib/parser.ts tests/parser.validation.ts` | Space-separated patterns |
|
|
1270
1319
|
| `KASEKI_MAX_DIFF_BYTES` | 200000 | Max diff size (200 KB) |
|
|
1271
1320
|
| `KASEKI_ALLOW_EMPTY_DIFF` | 0 | Set to `1` to allow empty diff with `KASEKI_TASK_MODE=patch` |
|
|
@@ -1277,6 +1326,8 @@ for a run that cannot publish.
|
|
|
1277
1326
|
|
|
1278
1327
|
API controllers may send either the direct fields (`changedFilesAllowlist`, `validationCommands`) or the structured aliases (`allowlist.include`, `validation.commands`). The scheduler normalizes both forms before launching the worker.
|
|
1279
1328
|
|
|
1329
|
+
Startup checks have two depths. Boot-only startup checks (`startupCheck: true`, `startupCheckMode: "boot"`, or `KASEKI_DRY_RUN=1 KASEKI_STARTUP_CHECK_MODE=boot`) use the minimal container boot path to verify runtime tools, mounts, and secrets without cloning the repository. Baseline validation startup checks (`startupCheckMode: "baseline-validation"`, or a startup check with validation commands) keep dry-run/Pi-skipping behavior but invoke `/usr/local/bin/kaseki-agent` far enough to clone the repository, prepare dependencies, and execute the pre-agent validation commands. A failure in this mode means the requested baseline already failed before any Pi-authored changes existed; inspect `pre-validation.log` and `pre-validation-timings.tsv`.
|
|
1330
|
+
|
|
1280
1331
|
### Paths and Caching
|
|
1281
1332
|
|
|
1282
1333
|
| Variable | Default | Notes |
|
|
@@ -132,10 +132,10 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
132
132
|
publish_mode: z.ZodOptional<z.ZodOptional<z.ZodEnum<["auto", "on", "off"]>>>;
|
|
133
133
|
}, "strip", z.ZodTypeAny, {
|
|
134
134
|
app_enabled?: boolean | undefined;
|
|
135
|
-
publish_mode?: "
|
|
135
|
+
publish_mode?: "auto" | "off" | "on" | undefined;
|
|
136
136
|
}, {
|
|
137
137
|
app_enabled?: boolean | undefined;
|
|
138
|
-
publish_mode?: "
|
|
138
|
+
publish_mode?: "auto" | "off" | "on" | undefined;
|
|
139
139
|
}>>;
|
|
140
140
|
docker: z.ZodOptional<z.ZodObject<{
|
|
141
141
|
image: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
@@ -254,7 +254,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
254
254
|
} | undefined;
|
|
255
255
|
github?: {
|
|
256
256
|
app_enabled?: boolean | undefined;
|
|
257
|
-
publish_mode?: "
|
|
257
|
+
publish_mode?: "auto" | "off" | "on" | undefined;
|
|
258
258
|
} | undefined;
|
|
259
259
|
docker?: {
|
|
260
260
|
image?: string | undefined;
|
|
@@ -325,7 +325,7 @@ export declare const ConfigSchema: z.ZodObject<{
|
|
|
325
325
|
} | undefined;
|
|
326
326
|
github?: {
|
|
327
327
|
app_enabled?: boolean | undefined;
|
|
328
|
-
publish_mode?: "
|
|
328
|
+
publish_mode?: "auto" | "off" | "on" | undefined;
|
|
329
329
|
} | undefined;
|
|
330
330
|
docker?: {
|
|
331
331
|
image?: string | undefined;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GitHubAppPrivateKeyValidationResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
normalized?: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
remediation?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function normalizeGitHubAppPrivateKey(value: string): string;
|
|
8
|
+
export declare function validateGitHubAppPrivateKey(value: string): GitHubAppPrivateKeyValidationResult;
|
|
9
|
+
//# sourceMappingURL=github-app-private-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-app-private-key.d.ts","sourceRoot":"","sources":["../src/github-app-private-key.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mCAAmC;IAClD,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA0DD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBlE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,mCAAmC,CAiD9F"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
const PRIVATE_KEY_HEADER_PATTERN = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----/;
|
|
3
|
+
const ANY_PEM_HEADER_PATTERN = /-----BEGIN [^-]+-----/;
|
|
4
|
+
const MAX_CRYPTO_ERROR_LENGTH = 240;
|
|
5
|
+
function hasPrivateKeyPemHeader(value) {
|
|
6
|
+
return PRIVATE_KEY_HEADER_PATTERN.test(value);
|
|
7
|
+
}
|
|
8
|
+
function looksLikeBase64(value) {
|
|
9
|
+
const compact = value.replace(/\s+/g, '');
|
|
10
|
+
return (compact.length > 0 &&
|
|
11
|
+
compact.length % 4 === 0 &&
|
|
12
|
+
/^[A-Za-z0-9+/]+={0,2}$/.test(compact));
|
|
13
|
+
}
|
|
14
|
+
function removeMatchingOuterQuotes(value) {
|
|
15
|
+
if (value.length >= 2) {
|
|
16
|
+
const first = value[0];
|
|
17
|
+
const last = value[value.length - 1];
|
|
18
|
+
if ((first === '"' || first === "'") && first === last) {
|
|
19
|
+
return value.slice(1, -1);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
function normalizePrivateKeyText(value) {
|
|
25
|
+
return removeMatchingOuterQuotes(value.replace(/^\uFEFF/, '').trim().replace(/\\n/g, '\n'));
|
|
26
|
+
}
|
|
27
|
+
function rewrapPrivateKeyPem(value) {
|
|
28
|
+
return value.replace(/-----BEGIN ([A-Z0-9 ]*PRIVATE KEY)-----([\s\S]*?)-----END \1-----/g, (_match, type, body) => {
|
|
29
|
+
const compactBody = body.replace(/\s+/g, '');
|
|
30
|
+
const bodyLines = compactBody.match(/.{1,64}/g) || [];
|
|
31
|
+
return `-----BEGIN ${type}-----\n${bodyLines.join('\n')}\n-----END ${type}-----\n`;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function sanitizeCryptoError(error) {
|
|
35
|
+
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
36
|
+
const normalizedMessage = rawMessage.replace(/\s+/g, ' ').trim();
|
|
37
|
+
if (normalizedMessage.length <= MAX_CRYPTO_ERROR_LENGTH) {
|
|
38
|
+
return normalizedMessage;
|
|
39
|
+
}
|
|
40
|
+
return `${normalizedMessage.slice(0, MAX_CRYPTO_ERROR_LENGTH)}...`;
|
|
41
|
+
}
|
|
42
|
+
export function normalizeGitHubAppPrivateKey(value) {
|
|
43
|
+
let normalizedPem = rewrapPrivateKeyPem(normalizePrivateKeyText(value));
|
|
44
|
+
if (!hasPrivateKeyPemHeader(normalizedPem) && looksLikeBase64(normalizedPem)) {
|
|
45
|
+
const decodedPem = Buffer.from(normalizedPem.replace(/\s+/g, ''), 'base64').toString('utf8');
|
|
46
|
+
if (hasPrivateKeyPemHeader(decodedPem) ||
|
|
47
|
+
ANY_PEM_HEADER_PATTERN.test(decodedPem)) {
|
|
48
|
+
normalizedPem = rewrapPrivateKeyPem(normalizePrivateKeyText(decodedPem));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return normalizedPem;
|
|
52
|
+
}
|
|
53
|
+
export function validateGitHubAppPrivateKey(value) {
|
|
54
|
+
const normalized = normalizeGitHubAppPrivateKey(value);
|
|
55
|
+
if (normalized.includes('-----BEGIN OPENSSH PRIVATE KEY-----')) {
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
error: 'GitHub App private key uses OpenSSH format. GitHub App keys must be the PEM downloaded from GitHub App settings.',
|
|
59
|
+
remediation: 'Download a new private key from the GitHub App settings page and store that PEM content in the github_app_private_key secret file.',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (normalized.includes('-----BEGIN ENCRYPTED PRIVATE KEY-----')) {
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: 'GitHub App private key is encrypted. Encrypted keys are not supported unless passphrase support is added.',
|
|
66
|
+
remediation: 'Store an unencrypted GitHub App private key PEM in the github_app_private_key secret file.',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (/-----BEGIN [^-]*(PUBLIC KEY|CERTIFICATE)-----/.test(normalized)) {
|
|
70
|
+
return {
|
|
71
|
+
ok: false,
|
|
72
|
+
error: 'GitHub App private key file contains a public key or certificate; this is not the GitHub App private key.',
|
|
73
|
+
remediation: 'Replace github_app_private_key with the private-key PEM downloaded from GitHub App settings, not a public key or certificate.',
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (!hasPrivateKeyPemHeader(normalized)) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: 'GitHub App private key file does not contain a private-key PEM header after normalization/base64 decode. Expected -----BEGIN ... PRIVATE KEY-----.',
|
|
80
|
+
remediation: 'The github_app_private_key secret file must contain the complete PEM private key downloaded from GitHub App settings, including BEGIN and END lines.',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
crypto.createPrivateKey(normalized);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
error: `GitHub App private key is not a valid PEM private key: ${sanitizeCryptoError(error)}`,
|
|
90
|
+
remediation: 'Regenerate the GitHub App private key in GitHub App settings and replace the github_app_private_key secret file with the complete downloaded PEM.',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
ok: true,
|
|
95
|
+
normalized,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=github-app-private-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-app-private-key.js","sourceRoot":"","sources":["../src/github-app-private-key.ts"],"names":[],"mappings":"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"}
|
package/dist/github-app-token.js
CHANGED
|
@@ -15,10 +15,21 @@
|
|
|
15
15
|
import fs from 'fs';
|
|
16
16
|
import crypto from 'crypto';
|
|
17
17
|
import https from 'https';
|
|
18
|
+
import { validateGitHubAppPrivateKey } from './github-app-private-key.js';
|
|
18
19
|
const APP_ID = process.argv[2];
|
|
19
20
|
const PRIVATE_KEY_FILE = process.argv[3];
|
|
20
21
|
const OWNER = process.argv[4];
|
|
21
22
|
const REPO = process.argv[5];
|
|
23
|
+
function loadAndValidatePrivateKey(privateKeyFile) {
|
|
24
|
+
const validation = validateGitHubAppPrivateKey(fs.readFileSync(privateKeyFile, 'utf8'));
|
|
25
|
+
if (!validation.ok || !validation.normalized) {
|
|
26
|
+
const message = validation.remediation
|
|
27
|
+
? `${validation.error} ${validation.remediation}`
|
|
28
|
+
: validation.error;
|
|
29
|
+
throw new Error(message || 'GitHub App private key is not valid.');
|
|
30
|
+
}
|
|
31
|
+
return crypto.createPrivateKey(validation.normalized);
|
|
32
|
+
}
|
|
22
33
|
async function generateJWT(appId, privateKey) {
|
|
23
34
|
const now = Math.floor(Date.now() / 1000);
|
|
24
35
|
const iat = now - 60; // account for clock skew
|
|
@@ -124,8 +135,8 @@ async function main() {
|
|
|
124
135
|
process.exit(1);
|
|
125
136
|
}
|
|
126
137
|
try {
|
|
127
|
-
// Read private key
|
|
128
|
-
const privateKey =
|
|
138
|
+
// Read and validate private key
|
|
139
|
+
const privateKey = loadAndValidatePrivateKey(PRIVATE_KEY_FILE);
|
|
129
140
|
// Generate JWT
|
|
130
141
|
const jwt = await generateJWT(APP_ID, privateKey);
|
|
131
142
|
// Get installation ID
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-app-token.js","sourceRoot":"","sources":["../src/github-app-token.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"github-app-token.js","sourceRoot":"","sources":["../src/github-app-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-scheduler.d.ts","sourceRoot":"","sources":["../src/job-scheduler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAoC,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAclD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAa;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,CAAQ;IAClE,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,iBAAiB,CAA6C;IACtE,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,aAAa,CAAC,CAAmC;IACzD,OAAO,CAAC,kBAAkB,CAAwB;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;gBAErC,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC;IAcrH;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;IAoDlD;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS;IAInC;;;;OAIG;IACH,QAAQ,IAAI,GAAG,EAAE;IAIjB;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS;IA0EtC;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,UAAU;
|
|
1
|
+
{"version":3,"file":"job-scheduler.d.ts","sourceRoot":"","sources":["../src/job-scheduler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAE,UAAU,EAAoC,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAclD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAa;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,CAAQ;IAClE,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAqC;IAC/D,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,iBAAiB,CAA6C;IACtE,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,aAAa,CAAC,CAAmC;IACzD,OAAO,CAAC,kBAAkB,CAAwB;IAClD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;gBAErC,MAAM,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC;IAcrH;;OAEG;IACG,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;IAoDlD;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS;IAInC;;;;OAIG;IACH,QAAQ,IAAI,GAAG,EAAE;IAIjB;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS;IA0EtC;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;OAEG;IACH,OAAO,CAAC,UAAU;IAiNlB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,oBAAoB;IAkB5B,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,mBAAmB;IAuD3B,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,4BAA4B;IA0BpC,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,yBAAyB;IAIjC;;OAEG;IACH,OAAO,CAAC,WAAW;IAsCnB,OAAO,CAAC,gBAAgB;IAYxB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,MAAM,GAAG,IAAI;IAS5D,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAoB5E,OAAO,CAAC,uBAAuB;IAgB/B,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,yBAAyB;IAajC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,cAAc,IAAI;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE;IAQ7E,YAAY,IAAI;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE;IAqBrD;;OAEG;IACH,QAAQ,IAAI,IAAI;CAqDjB"}
|
package/dist/job-scheduler.js
CHANGED
|
@@ -224,24 +224,33 @@ export class JobScheduler {
|
|
|
224
224
|
// directory so the API does not accidentally reserve the final result path.
|
|
225
225
|
KASEKI_LOG_DIR: this.config.resultsDir,
|
|
226
226
|
KASEKI_TASK_MODE: job.request.taskMode || this.config.defaultTaskMode,
|
|
227
|
-
|
|
227
|
+
KASEKI_PUBLISH_MODE: job.request.publishMode || 'draft_pr',
|
|
228
228
|
KASEKI_MAX_DIFF_BYTES: String(job.request.maxDiffBytes || this.config.maxDiffBytes),
|
|
229
229
|
KASEKI_AGENT_TIMEOUT_SECONDS: String(effectiveTimeoutSeconds),
|
|
230
230
|
};
|
|
231
231
|
this.populateGitHubAppEnv(env);
|
|
232
|
+
const validationCommands = job.request.validationCommands ?? job.request.validation?.commands;
|
|
233
|
+
const startupCheckMode = job.request.startupCheckMode || (job.request.startupCheck && validationCommands ? 'baseline-validation' : 'boot');
|
|
232
234
|
if (job.request.startupCheck) {
|
|
233
235
|
env.KASEKI_DRY_RUN = '1';
|
|
234
236
|
env.KASEKI_TASK_MODE = 'inspect';
|
|
235
|
-
env.
|
|
237
|
+
env.KASEKI_STARTUP_CHECK_MODE = startupCheckMode;
|
|
238
|
+
if (startupCheckMode === 'baseline-validation') {
|
|
239
|
+
env.KASEKI_BASELINE_VALIDATION_DRY_RUN = '1';
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
env.KASEKI_VALIDATION_COMMANDS = 'none';
|
|
243
|
+
}
|
|
236
244
|
env.TASK_PROMPT =
|
|
237
245
|
job.request.taskPrompt ||
|
|
238
|
-
|
|
246
|
+
(startupCheckMode === 'baseline-validation'
|
|
247
|
+
? 'Run Kaseki baseline validation startup checks only. Clone the repo, install dependencies, run pre-agent validation, then exit without Pi agent work.'
|
|
248
|
+
: 'Run Kaseki startup checks only. Verify container boot and dependencies, then exit without agent work.');
|
|
239
249
|
}
|
|
240
250
|
const changedFilesAllowlist = job.request.changedFilesAllowlist ?? job.request.allowlist?.include;
|
|
241
251
|
if (changedFilesAllowlist) {
|
|
242
252
|
env.KASEKI_CHANGED_FILES_ALLOWLIST = changedFilesAllowlist.join(' ');
|
|
243
253
|
}
|
|
244
|
-
const validationCommands = job.request.validationCommands ?? job.request.validation?.commands;
|
|
245
254
|
if (validationCommands) {
|
|
246
255
|
env.KASEKI_VALIDATION_COMMANDS = validationCommands.join(';');
|
|
247
256
|
}
|