kodu 1.1.13 → 1.1.15

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.
Files changed (88) hide show
  1. package/AGENTS.md +184 -199
  2. package/README.md +32 -3
  3. package/dist/src/app.module.js +2 -0
  4. package/dist/src/app.module.js.map +1 -1
  5. package/dist/src/commands/init/init.command.js +16 -0
  6. package/dist/src/commands/init/init.command.js.map +1 -1
  7. package/dist/src/commands/ops/ops.command.d.ts +4 -0
  8. package/dist/src/commands/ops/ops.command.js +39 -0
  9. package/dist/src/commands/ops/ops.command.js.map +1 -0
  10. package/dist/src/commands/ops/ops.module.d.ts +2 -0
  11. package/dist/src/commands/ops/ops.module.js +33 -0
  12. package/dist/src/commands/ops/ops.module.js.map +1 -0
  13. package/dist/src/commands/ops/ops.types.d.ts +13 -0
  14. package/dist/src/commands/ops/ops.types.js +12 -0
  15. package/dist/src/commands/ops/ops.types.js.map +1 -0
  16. package/dist/src/commands/ops/ops.utils.d.ts +13 -0
  17. package/dist/src/commands/ops/ops.utils.js +117 -0
  18. package/dist/src/commands/ops/ops.utils.js.map +1 -0
  19. package/dist/src/commands/ops/subcommands/ops-env.command.d.ts +17 -0
  20. package/dist/src/commands/ops/subcommands/ops-env.command.js +109 -0
  21. package/dist/src/commands/ops/subcommands/ops-env.command.js.map +1 -0
  22. package/dist/src/commands/ops/subcommands/ops-routes.command.d.ts +18 -0
  23. package/dist/src/commands/ops/subcommands/ops-routes.command.js +166 -0
  24. package/dist/src/commands/ops/subcommands/ops-routes.command.js.map +1 -0
  25. package/dist/src/commands/ops/subcommands/ops-service.command.d.ts +16 -0
  26. package/dist/src/commands/ops/subcommands/ops-service.command.js +128 -0
  27. package/dist/src/commands/ops/subcommands/ops-service.command.js.map +1 -0
  28. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.d.ts +9 -0
  29. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js +60 -0
  30. package/dist/src/commands/ops/subcommands/ops-sysinfo.command.js.map +1 -0
  31. package/dist/src/commands/pack/pack.command.js +1 -2
  32. package/dist/src/commands/pack/pack.command.js.map +1 -1
  33. package/dist/src/core/config/config.schema.d.ts +28 -0
  34. package/dist/src/core/config/config.schema.js +19 -0
  35. package/dist/src/core/config/config.schema.js.map +1 -1
  36. package/dist/src/core/file-system/fs.service.d.ts +4 -1
  37. package/dist/src/core/file-system/fs.service.js +57 -21
  38. package/dist/src/core/file-system/fs.service.js.map +1 -1
  39. package/dist/src/shared/constants.d.ts +1 -0
  40. package/dist/src/shared/constants.js +2 -1
  41. package/dist/src/shared/constants.js.map +1 -1
  42. package/dist/src/shared/ssh/ssh.module.d.ts +2 -0
  43. package/dist/src/shared/ssh/ssh.module.js +21 -0
  44. package/dist/src/shared/ssh/ssh.module.js.map +1 -0
  45. package/dist/src/shared/ssh/ssh.service.d.ts +11 -0
  46. package/dist/src/shared/ssh/ssh.service.js +53 -0
  47. package/dist/src/shared/ssh/ssh.service.js.map +1 -0
  48. package/dist/src/shared/tokenizer/tokenizer.service.js +1 -1
  49. package/dist/src/shared/tokenizer/tokenizer.service.js.map +1 -1
  50. package/dist/tsconfig.build.tsbuildinfo +1 -1
  51. package/docs/plans/2026-03-01-agentops-design.md +194 -0
  52. package/docs/plans/2026-03-01-agentops-implementation.md +358 -0
  53. package/kodu.json +15 -0
  54. package/kodu.schema.json +59 -0
  55. package/package.json +1 -1
  56. package/src/app.module.ts +2 -0
  57. package/src/commands/init/init.command.ts +16 -0
  58. package/src/commands/ops/ops.command.ts +30 -0
  59. package/src/commands/ops/ops.module.ts +20 -0
  60. package/src/commands/ops/ops.types.ts +24 -0
  61. package/src/commands/ops/ops.utils.ts +156 -0
  62. package/src/commands/ops/subcommands/ops-env.command.ts +121 -0
  63. package/src/commands/ops/subcommands/ops-routes.command.ts +185 -0
  64. package/src/commands/ops/subcommands/ops-service.command.ts +154 -0
  65. package/src/commands/ops/subcommands/ops-sysinfo.command.ts +53 -0
  66. package/src/commands/pack/pack.command.ts +1 -2
  67. package/src/core/config/config.schema.ts +23 -0
  68. package/src/core/file-system/fs.service.ts +72 -23
  69. package/src/shared/constants.ts +1 -0
  70. package/src/shared/ssh/ssh.module.ts +8 -0
  71. package/src/shared/ssh/ssh.service.ts +61 -0
  72. package/src/shared/tokenizer/tokenizer.service.ts +2 -2
  73. package/.cursor/commands/openspec-apply.md +0 -23
  74. package/.cursor/commands/openspec-archive.md +0 -27
  75. package/.cursor/commands/openspec-proposal.md +0 -28
  76. package/.windsurf/workflows/openspec-apply.md +0 -21
  77. package/.windsurf/workflows/openspec-archive.md +0 -25
  78. package/.windsurf/workflows/openspec-proposal.md +0 -26
  79. package/openspec/AGENTS.md +0 -456
  80. package/openspec/changes/archive/2026-01-26-translate-project-to-english/design.md +0 -30
  81. package/openspec/changes/archive/2026-01-26-translate-project-to-english/proposal.md +0 -17
  82. package/openspec/changes/archive/2026-01-26-translate-project-to-english/specs/ai/spec.md +0 -26
  83. package/openspec/changes/archive/2026-01-26-translate-project-to-english/specs/cleaner/spec.md +0 -26
  84. package/openspec/changes/archive/2026-01-26-translate-project-to-english/specs/config/spec.md +0 -22
  85. package/openspec/changes/archive/2026-01-26-translate-project-to-english/specs/ui/spec.md +0 -33
  86. package/openspec/changes/archive/2026-01-26-translate-project-to-english/tasks.md +0 -33
  87. package/openspec/project.md +0 -72
  88. package/openspec/specs/cleaner/spec.md +0 -31
@@ -0,0 +1,194 @@
1
+ # AgentOps Design
2
+
3
+ ## Context
4
+
5
+ Add a new `kodu ops` namespace for AI agents to manage remote servers through SSH. The output contract is strict JSON in stdout/stderr with no spinner UI, no colors, and no interactive prompts.
6
+
7
+ ## Goals
8
+
9
+ - Add project-local config for remote server aliases in `kodu.json`.
10
+ - Add a shared SSH abstraction over `execa` that does not throw on remote command failures.
11
+ - Add `kodu ops` subcommands for server diagnostics, env management, Caddy routes, and Docker Compose service lifecycle.
12
+ - Preserve machine-readable behavior for all success and error paths.
13
+
14
+ ## Config Design
15
+
16
+ Extend `src/core/config/config.schema.ts` with optional `ops` section:
17
+
18
+ - `ops.servers` is a record keyed by alias (`prod`, `dev`, etc.).
19
+ - Each server includes:
20
+ - `host`, `user`, `sshKeyPath`
21
+ - `port` default `22`
22
+ - optional `description`
23
+ - optional `paths` with:
24
+ - `apps` default `/var/agent-apps`
25
+ - optional `caddy` for custom Caddy project path
26
+ - optional `env` map for SSH process environment variables
27
+
28
+ All commands validate:
29
+
30
+ 1. alias exists in `ops.servers`
31
+ 2. ssh key file exists (`fs.access`)
32
+
33
+ ## SSH Shared Module Design
34
+
35
+ Create `src/shared/ssh/` with:
36
+
37
+ - `ssh.module.ts`
38
+ - `ssh.service.ts`
39
+
40
+ `SshService.execute(serverConfig, command)` behavior:
41
+
42
+ - Builds `ssh` args:
43
+ - `-i <keyPath>`
44
+ - `-p <port>`
45
+ - `-o StrictHostKeyChecking=no`
46
+ - `-o ConnectTimeout=10`
47
+ - `<user>@<host>`
48
+ - `<command>`
49
+ - Runs via `execa('ssh', args, { env })`
50
+ - Returns:
51
+
52
+ ```ts
53
+ type SshResult = {
54
+ success: boolean;
55
+ stdout: string;
56
+ stderr: string;
57
+ exitCode: number;
58
+ error?: string;
59
+ };
60
+ ```
61
+
62
+ No throw for SSH command failures. Local/system failures also map to `SshResult` with `success: false`.
63
+
64
+ ## Commands Design
65
+
66
+ Create `src/commands/ops/`:
67
+
68
+ - `ops.module.ts`
69
+ - `ops.command.ts`
70
+ - `subcommands/ops-sysinfo.command.ts`
71
+ - `subcommands/ops-env.command.ts`
72
+ - `subcommands/ops-routes.command.ts`
73
+ - `subcommands/ops-service.command.ts`
74
+
75
+ Register `OpsModule` in `src/app.module.ts`.
76
+
77
+ All `ops` commands:
78
+
79
+ - no `UiService`
80
+ - no spinners
81
+ - no prompts
82
+ - print JSON only:
83
+ - success/data via `console.log(JSON.stringify(...))`
84
+ - fatal CLI errors via `console.error(JSON.stringify(...))` and `process.exitCode = 1`
85
+
86
+ ## JSON Contracts
87
+
88
+ Success pattern:
89
+
90
+ ```json
91
+ { "status": "ok", "data": {} }
92
+ ```
93
+
94
+ Remote command failure pattern:
95
+
96
+ ```json
97
+ {
98
+ "status": "error",
99
+ "code": 255,
100
+ "stderr": "ssh: connect to host ... port 22: Connection refused",
101
+ "command": "uptime"
102
+ }
103
+ ```
104
+
105
+ Local validation/fatal pattern:
106
+
107
+ ```json
108
+ {
109
+ "status": "error",
110
+ "code": "VALIDATION_ERROR",
111
+ "error": "Server alias 'prod' not found in kodu.json"
112
+ }
113
+ ```
114
+
115
+ ## Subcommand Behavior
116
+
117
+ ### `ops sysinfo <alias>`
118
+
119
+ Runs the agreed payload and proxies JSON response:
120
+
121
+ - uptime
122
+ - root disk usage
123
+ - free memory (MB)
124
+
125
+ ### `ops env <alias> <action> <project>`
126
+
127
+ Actions: `get`, `set`, `unset`.
128
+
129
+ - target file: `${appsPath}/${project}/.env`
130
+ - `get`: read file contents
131
+ - `set`: update or append key
132
+ - `unset`: remove key line
133
+
134
+ Required options:
135
+
136
+ - `set`: `--key`, `--val`
137
+ - `unset`: `--key`
138
+
139
+ ### `ops routes <alias> <action>`
140
+
141
+ Use Caddy project workflow from `/home/dex/Рабочий стол/Work/caddy-caddy` model:
142
+
143
+ - Caddy runs via Docker Compose in separate project folder
144
+ - config source is `data/Caddyfile`
145
+ - apply command is `./caddy.sh` (default apply mode)
146
+
147
+ Actions:
148
+
149
+ - `list`: return raw Caddyfile
150
+ - `add`: add domain `reverse_proxy` block, then run `./caddy.sh`
151
+ - `remove`: remove domain block, then run `./caddy.sh`
152
+ - `update`: update domain upstream, then run `./caddy.sh`
153
+
154
+ Path resolution for Caddy project:
155
+
156
+ - `server.paths.caddy` if configured
157
+ - fallback `${appsPath}/caddy`
158
+
159
+ ### `ops service <alias> <action> <project>`
160
+
161
+ Actions: `clone`, `pull`, `up`, `down`, `logs`, `status`.
162
+
163
+ - `clone`: clone repo to project path (skip/fail if exists)
164
+ - `pull`: git pull in project dir
165
+ - `up`: docker compose up -d
166
+ - `down`: docker compose down
167
+ - `logs`: docker compose logs
168
+ - `status`: docker compose ps (json format when available)
169
+
170
+ ## Caddyfile Editing Strategy
171
+
172
+ For `routes add/remove/update`, perform robust remote text transforms with a small `node -e` script executed over SSH:
173
+
174
+ - read Caddyfile
175
+ - locate target domain block
176
+ - apply deterministic update
177
+ - write to temp file then rename
178
+ - return structured JSON from remote helper
179
+
180
+ Then run `cd <caddyPath> && ./caddy.sh`.
181
+
182
+ If domain not found for `remove`/`update`, return JSON error with code `NOT_FOUND`.
183
+
184
+ ## Error Handling Rules
185
+
186
+ - SSH exit code non-zero must not crash command.
187
+ - Return JSON with `status:error`, numeric `code`, `stderr`, and original `command`.
188
+ - Keep stdout/stderr machine-friendly; no additional prose lines.
189
+
190
+ ## Out of Scope
191
+
192
+ - Caddy Admin API integration.
193
+ - Interactive operator UX.
194
+ - Non-JSON presentation layer.
@@ -0,0 +1,358 @@
1
+ # AgentOps Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Add a new JSON-only `kodu ops` command namespace for remote server diagnostics and operations over SSH.
6
+
7
+ **Architecture:** Extend config with an optional `ops.servers` map, add a shared `SshService` that wraps `execa('ssh')` and never throws for remote failures, and implement `ops` subcommands (`sysinfo`, `env`, `routes`, `service`) that validate inputs locally and return strict JSON responses.
8
+
9
+ **Tech Stack:** NestJS + nest-commander, zod, execa, node:fs/promises.
10
+
11
+ ---
12
+
13
+ ### Task 1: Extend Config Schema For Ops
14
+
15
+ **Files:**
16
+ - Modify: `src/core/config/config.schema.ts`
17
+
18
+ **Step 1: Write the failing check (type-level usage target)**
19
+
20
+ Use this target snippet as acceptance criteria while editing:
21
+
22
+ ```ts
23
+ const cfg = configService.getConfig();
24
+ const maybeServer = cfg.ops?.servers?.prod;
25
+ ```
26
+
27
+ **Step 2: Run type check to confirm current gap**
28
+
29
+ Run: `npm run ts:check`
30
+ Expected: type errors in future ops command code until `ops` is added.
31
+
32
+ **Step 3: Add minimal schema/types**
33
+
34
+ Add `serverConfigSchema`, `opsSchema`, and `ops: opsSchema.optional()` in root schema.
35
+
36
+ **Step 4: Run type check**
37
+
38
+ Run: `npm run ts:check`
39
+ Expected: PASS for config layer.
40
+
41
+ **Step 5: Commit**
42
+
43
+ ```bash
44
+ git add src/core/config/config.schema.ts
45
+ git commit -m "feat(config): add ops servers schema"
46
+ ```
47
+
48
+ ### Task 2: Add Shared SSH Module And Service
49
+
50
+ **Files:**
51
+ - Create: `src/shared/ssh/ssh.service.ts`
52
+ - Create: `src/shared/ssh/ssh.module.ts`
53
+
54
+ **Step 1: Define failing usage target**
55
+
56
+ Target call shape:
57
+
58
+ ```ts
59
+ const result = await sshService.execute(server, 'uptime');
60
+ if (!result.success) {
61
+ console.log(result.stderr);
62
+ }
63
+ ```
64
+
65
+ **Step 2: Run type check to verify service does not exist yet**
66
+
67
+ Run: `npm run ts:check`
68
+ Expected: FAIL when referenced by future ops command wiring.
69
+
70
+ **Step 3: Implement minimal `SshService`**
71
+
72
+ Implement:
73
+ - `SshResult` type
74
+ - `execute(serverConfig, command)`
75
+ - `execa('ssh', args, { env: serverConfig.env })`
76
+ - capture non-zero exits and system errors without throw
77
+
78
+ **Step 4: Export via `SshModule`**
79
+
80
+ Use Nest module pattern consistent with shared modules.
81
+
82
+ **Step 5: Run type check**
83
+
84
+ Run: `npm run ts:check`
85
+ Expected: PASS for ssh module/service.
86
+
87
+ **Step 6: Commit**
88
+
89
+ ```bash
90
+ git add src/shared/ssh/ssh.service.ts src/shared/ssh/ssh.module.ts
91
+ git commit -m "feat(ops): add shared ssh service"
92
+ ```
93
+
94
+ ### Task 3: Scaffold Ops Command Module
95
+
96
+ **Files:**
97
+ - Create: `src/commands/ops/ops.module.ts`
98
+ - Create: `src/commands/ops/ops.command.ts`
99
+ - Modify: `src/app.module.ts`
100
+
101
+ **Step 1: Create failing command target**
102
+
103
+ Expected CLI shape:
104
+
105
+ ```bash
106
+ kodu ops --help
107
+ ```
108
+
109
+ **Step 2: Run build to confirm command missing**
110
+
111
+ Run: `npm run build`
112
+ Expected: `ops` command not present before scaffolding.
113
+
114
+ **Step 3: Implement root ops module/command**
115
+
116
+ Add root namespace command and register providers/imports.
117
+
118
+ **Step 4: Register in AppModule**
119
+
120
+ Import `OpsModule` (and `SshModule` if needed at root level).
121
+
122
+ **Step 5: Run build**
123
+
124
+ Run: `npm run build`
125
+ Expected: PASS and `kodu ops --help` shows namespace.
126
+
127
+ **Step 6: Commit**
128
+
129
+ ```bash
130
+ git add src/commands/ops/ops.module.ts src/commands/ops/ops.command.ts src/app.module.ts
131
+ git commit -m "feat(ops): register ops root namespace"
132
+ ```
133
+
134
+ ### Task 4: Implement Shared Ops Validation + JSON Helpers
135
+
136
+ **Files:**
137
+ - Create: `src/commands/ops/ops.types.ts`
138
+ - Create: `src/commands/ops/ops.utils.ts`
139
+
140
+ **Step 1: Define failing usage target**
141
+
142
+ Helpers should support:
143
+
144
+ ```ts
145
+ const server = await resolveServerOrThrow(config, alias);
146
+ await assertSshKeyExists(server);
147
+ printOk({ ping: true });
148
+ printSshError(result, command);
149
+ ```
150
+
151
+ **Step 2: Implement helpers**
152
+
153
+ Include:
154
+ - server alias resolution
155
+ - ssh key path normalization (`absolute` or relative to `process.cwd()`)
156
+ - `fs.access` validation
157
+ - consistent JSON output builders
158
+
159
+ **Step 3: Run type check**
160
+
161
+ Run: `npm run ts:check`
162
+ Expected: PASS.
163
+
164
+ **Step 4: Commit**
165
+
166
+ ```bash
167
+ git add src/commands/ops/ops.types.ts src/commands/ops/ops.utils.ts
168
+ git commit -m "feat(ops): add validation and json response helpers"
169
+ ```
170
+
171
+ ### Task 5: Implement `ops sysinfo`
172
+
173
+ **Files:**
174
+ - Create: `src/commands/ops/subcommands/ops-sysinfo.command.ts`
175
+ - Modify: `src/commands/ops/ops.module.ts`
176
+
177
+ **Step 1: Write failing command run target**
178
+
179
+ ```bash
180
+ kodu ops sysinfo dev
181
+ ```
182
+
183
+ Expected shape:
184
+
185
+ ```json
186
+ {"status":"ok","data":{"uptime":"...","disk_usage":"...","mem_free":"..."}}
187
+ ```
188
+
189
+ **Step 2: Run build or command to confirm missing subcommand**
190
+
191
+ Run: `npm run build`
192
+ Expected: missing subcommand before implementation.
193
+
194
+ **Step 3: Implement command**
195
+
196
+ Use agreed SSH payload and `SshService`. Map non-zero SSH result to JSON error without crash.
197
+
198
+ **Step 4: Verify**
199
+
200
+ Run: `npm run build && npm run ts:check`
201
+ Expected: PASS.
202
+
203
+ **Step 5: Commit**
204
+
205
+ ```bash
206
+ git add src/commands/ops/subcommands/ops-sysinfo.command.ts src/commands/ops/ops.module.ts
207
+ git commit -m "feat(ops): add sysinfo subcommand"
208
+ ```
209
+
210
+ ### Task 6: Implement `ops env`
211
+
212
+ **Files:**
213
+ - Create: `src/commands/ops/subcommands/ops-env.command.ts`
214
+ - Modify: `src/commands/ops/ops.module.ts`
215
+
216
+ **Step 1: Write failing run targets**
217
+
218
+ ```bash
219
+ kodu ops env dev get my-app
220
+ kodu ops env dev set my-app --key PORT --val 3001
221
+ kodu ops env dev unset my-app --key PORT
222
+ ```
223
+
224
+ **Step 2: Implement action validation and command builders**
225
+
226
+ Implement `get|set|unset`, enforce required flags, derive `.env` path from `apps` root.
227
+
228
+ **Step 3: Implement JSON-only outputs**
229
+
230
+ - success: `status: ok`
231
+ - remote failure: `status: error` + code/stderr/command
232
+ - local validation failure: JSON error in stderr
233
+
234
+ **Step 4: Verify**
235
+
236
+ Run: `npm run build && npm run ts:check`
237
+ Expected: PASS.
238
+
239
+ **Step 5: Commit**
240
+
241
+ ```bash
242
+ git add src/commands/ops/subcommands/ops-env.command.ts src/commands/ops/ops.module.ts
243
+ git commit -m "feat(ops): add env management subcommand"
244
+ ```
245
+
246
+ ### Task 7: Implement `ops routes` (list/add/remove/update)
247
+
248
+ **Files:**
249
+ - Create: `src/commands/ops/subcommands/ops-routes.command.ts`
250
+ - Modify: `src/commands/ops/ops.module.ts`
251
+
252
+ **Step 1: Write failing run targets**
253
+
254
+ ```bash
255
+ kodu ops routes dev list
256
+ kodu ops routes dev add --domain api.example.com --upstream 127.0.0.1:3000
257
+ kodu ops routes dev update --domain api.example.com --upstream 127.0.0.1:4000
258
+ kodu ops routes dev remove --domain api.example.com
259
+ ```
260
+
261
+ **Step 2: Implement path resolution and list**
262
+
263
+ - caddy root: `server.paths.caddy ?? path.posix.join(appsPath, 'caddy')`
264
+ - list: read `data/Caddyfile` and return raw text
265
+
266
+ **Step 3: Implement add/remove/update edits**
267
+
268
+ Execute remote `node -e` transformation scripts over SSH for deterministic block edits.
269
+
270
+ **Step 4: Apply config via caddy script**
271
+
272
+ After successful edit, run: `cd <caddyRoot> && ./caddy.sh`
273
+
274
+ **Step 5: Add NOT_FOUND behavior**
275
+
276
+ If domain absent for `remove`/`update`, return structured JSON error with code `NOT_FOUND`.
277
+
278
+ **Step 6: Verify**
279
+
280
+ Run: `npm run build && npm run ts:check`
281
+ Expected: PASS.
282
+
283
+ **Step 7: Commit**
284
+
285
+ ```bash
286
+ git add src/commands/ops/subcommands/ops-routes.command.ts src/commands/ops/ops.module.ts
287
+ git commit -m "feat(ops): add caddy routes management subcommand"
288
+ ```
289
+
290
+ ### Task 8: Implement `ops service`
291
+
292
+ **Files:**
293
+ - Create: `src/commands/ops/subcommands/ops-service.command.ts`
294
+ - Modify: `src/commands/ops/ops.module.ts`
295
+
296
+ **Step 1: Write failing run targets**
297
+
298
+ ```bash
299
+ kodu ops service dev status my-app
300
+ kodu ops service dev up my-app
301
+ ```
302
+
303
+ **Step 2: Implement actions**
304
+
305
+ Support `clone|pull|up|down|logs|status` with remote compose/git commands.
306
+
307
+ **Step 3: Add status JSON fallback**
308
+
309
+ Attempt `docker compose ps --format json`; fallback to raw `docker compose ps` output if unsupported.
310
+
311
+ **Step 4: Verify**
312
+
313
+ Run: `npm run build && npm run ts:check`
314
+ Expected: PASS.
315
+
316
+ **Step 5: Commit**
317
+
318
+ ```bash
319
+ git add src/commands/ops/subcommands/ops-service.command.ts src/commands/ops/ops.module.ts
320
+ git commit -m "feat(ops): add service lifecycle subcommand"
321
+ ```
322
+
323
+ ### Task 9: Full Validation And Manual Smoke Checks
324
+
325
+ **Files:**
326
+ - Modify: `kodu.json` (local test aliases only if needed)
327
+
328
+ **Step 1: Run static checks**
329
+
330
+ Run: `npm run check`
331
+ Expected: PASS.
332
+
333
+ **Step 2: Build final artifact**
334
+
335
+ Run: `npm run build`
336
+ Expected: PASS.
337
+
338
+ **Step 3: Manual command checks against test server**
339
+
340
+ Run and confirm valid JSON output each time:
341
+
342
+ ```bash
343
+ kodu ops sysinfo <alias>
344
+ kodu ops env <alias> get <project>
345
+ kodu ops routes <alias> list
346
+ kodu ops service <alias> status <project>
347
+ ```
348
+
349
+ **Step 4: Record results in PR/body notes**
350
+
351
+ Capture one success sample and one remote error sample to prove agent-readable behavior.
352
+
353
+ **Step 5: Commit (if test fixture/config changed)**
354
+
355
+ ```bash
356
+ git add <changed-files>
357
+ git commit -m "test(ops): validate json outputs and command flows"
358
+ ```
package/kodu.json CHANGED
@@ -36,6 +36,21 @@
36
36
  "useGitignore": true,
37
37
  "contentBasedBinaryDetection": false
38
38
  },
39
+ "ops": {
40
+ "servers": {
41
+ "dev": {
42
+ "host": "example.com",
43
+ "port": 22,
44
+ "user": "ubuntu",
45
+ "sshKeyPath": "~/.ssh/id_rsa",
46
+ "description": "Example AgentOps server",
47
+ "paths": {
48
+ "apps": "/var/agent-apps",
49
+ "caddy": "/var/agent-apps/caddy"
50
+ }
51
+ }
52
+ }
53
+ },
39
54
  "prompts": {
40
55
  "review": {
41
56
  "bug": ".kodu/prompts/review-bug.md",
package/kodu.schema.json CHANGED
@@ -173,6 +173,65 @@
173
173
  }
174
174
  },
175
175
  "additionalProperties": false
176
+ },
177
+ "ops": {
178
+ "type": "object",
179
+ "properties": {
180
+ "servers": {
181
+ "type": "object",
182
+ "propertyNames": {
183
+ "type": "string"
184
+ },
185
+ "additionalProperties": {
186
+ "type": "object",
187
+ "properties": {
188
+ "host": {
189
+ "type": "string"
190
+ },
191
+ "port": {
192
+ "default": 22,
193
+ "type": "number"
194
+ },
195
+ "user": {
196
+ "type": "string"
197
+ },
198
+ "sshKeyPath": {
199
+ "type": "string"
200
+ },
201
+ "description": {
202
+ "type": "string"
203
+ },
204
+ "paths": {
205
+ "type": "object",
206
+ "properties": {
207
+ "apps": {
208
+ "default": "/var/agent-apps",
209
+ "type": "string"
210
+ },
211
+ "caddy": {
212
+ "type": "string"
213
+ }
214
+ },
215
+ "required": ["apps"],
216
+ "additionalProperties": false
217
+ },
218
+ "env": {
219
+ "type": "object",
220
+ "propertyNames": {
221
+ "type": "string"
222
+ },
223
+ "additionalProperties": {
224
+ "type": "string"
225
+ }
226
+ }
227
+ },
228
+ "required": ["host", "port", "user", "sshKeyPath"],
229
+ "additionalProperties": false
230
+ }
231
+ }
232
+ },
233
+ "required": ["servers"],
234
+ "additionalProperties": false
176
235
  }
177
236
  },
178
237
  "required": ["cleaner", "packer"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kodu",
3
- "version": "1.1.13",
3
+ "version": "1.1.15",
4
4
  "description": "High-performance CLI to prepare codebase for LLMs, automate reviews, and draft commits.",
5
5
  "repository": {
6
6
  "type": "git",
package/src/app.module.ts CHANGED
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
2
2
  import { CleanModule } from './commands/clean/clean.module';
3
3
  import { CommitModule } from './commands/commit/commit.module';
4
4
  import { InitModule } from './commands/init/init.module';
5
+ import { OpsModule } from './commands/ops/ops.module';
5
6
  import { PackModule } from './commands/pack/pack.module';
6
7
  import { ReviewModule } from './commands/review/review.module';
7
8
  import { ConfigModule } from './core/config/config.module';
@@ -24,6 +25,7 @@ import { TokenizerModule } from './shared/tokenizer/tokenizer.module';
24
25
  CleanModule,
25
26
  ReviewModule,
26
27
  CommitModule,
28
+ OpsModule,
27
29
  ],
28
30
  })
29
31
  export class AppModule {}
@@ -37,6 +37,21 @@ export class InitCommand extends CommandRunner {
37
37
  $schema:
38
38
  'https://raw.githubusercontent.com/uxname/kodu/refs/heads/master/kodu.schema.json',
39
39
  llm: defaultLlmConfig,
40
+ ops: {
41
+ servers: {
42
+ dev: {
43
+ host: 'example.com',
44
+ port: 22,
45
+ user: 'ubuntu',
46
+ sshKeyPath: '~/.ssh/id_rsa',
47
+ description: 'Example AgentOps server',
48
+ paths: {
49
+ apps: '/var/agent-apps',
50
+ caddy: '/var/agent-apps/caddy',
51
+ },
52
+ },
53
+ },
54
+ },
40
55
  cleaner: {
41
56
  whitelist: ['//!'],
42
57
  keepJSDoc: true,
@@ -134,6 +149,7 @@ export class InitCommand extends CommandRunner {
134
149
  contentBasedBinaryDetection:
135
150
  defaultConfig.packer.contentBasedBinaryDetection,
136
151
  },
152
+ ops: defaultConfig.ops,
137
153
  prompts: {
138
154
  review: {
139
155
  bug: promptPaths.review.bug,