@kylecheng3146/agent-ops 0.0.1

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 (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/SECURITY.md +22 -0
  4. package/dist/packages/cli/src/args.js +322 -0
  5. package/dist/packages/cli/src/bin.js +290 -0
  6. package/dist/packages/cli/src/cli.js +80 -0
  7. package/dist/packages/cli/src/commands/config.js +8 -0
  8. package/dist/packages/cli/src/commands/doctor.js +32 -0
  9. package/dist/packages/cli/src/commands/index.js +16 -0
  10. package/dist/packages/cli/src/commands/init.js +65 -0
  11. package/dist/packages/cli/src/commands/review.js +71 -0
  12. package/dist/packages/cli/src/commands/task.js +141 -0
  13. package/dist/packages/cli/src/commands/trust.js +48 -0
  14. package/dist/packages/cli/src/commands/uninstall.js +58 -0
  15. package/dist/packages/cli/src/commands/update.js +58 -0
  16. package/dist/packages/cli/src/commands/verify.js +108 -0
  17. package/dist/packages/cli/src/output.js +53 -0
  18. package/dist/packages/cli/src/plan-output.js +28 -0
  19. package/dist/packages/cli/src/wizard.js +75 -0
  20. package/dist/runtime/src/adapters/claude/config.js +109 -0
  21. package/dist/runtime/src/adapters/claude/events.js +8 -0
  22. package/dist/runtime/src/adapters/claude/input.js +38 -0
  23. package/dist/runtime/src/adapters/claude/output.js +30 -0
  24. package/dist/runtime/src/adapters/codex/config.js +93 -0
  25. package/dist/runtime/src/adapters/codex/events.js +8 -0
  26. package/dist/runtime/src/adapters/codex/input.js +41 -0
  27. package/dist/runtime/src/adapters/codex/output.js +24 -0
  28. package/dist/runtime/src/config/explain.js +34 -0
  29. package/dist/runtime/src/config/load.js +25 -0
  30. package/dist/runtime/src/config/merge.js +170 -0
  31. package/dist/runtime/src/config/migrate.js +61 -0
  32. package/dist/runtime/src/contracts.js +1 -0
  33. package/dist/runtime/src/discovery/go.js +145 -0
  34. package/dist/runtime/src/discovery/index.js +40 -0
  35. package/dist/runtime/src/discovery/make.js +162 -0
  36. package/dist/runtime/src/discovery/node.js +175 -0
  37. package/dist/runtime/src/discovery/python.js +163 -0
  38. package/dist/runtime/src/discovery/rust.js +159 -0
  39. package/dist/runtime/src/discovery/types.js +1 -0
  40. package/dist/runtime/src/fs/hash.js +19 -0
  41. package/dist/runtime/src/fs/managed-block.js +90 -0
  42. package/dist/runtime/src/fs/manifest.js +24 -0
  43. package/dist/runtime/src/fs/mutation-worker.js +185 -0
  44. package/dist/runtime/src/fs/paths.js +96 -0
  45. package/dist/runtime/src/fs/transaction.js +498 -0
  46. package/dist/runtime/src/guardrails/destructive.js +207 -0
  47. package/dist/runtime/src/guardrails/evaluate.js +9 -0
  48. package/dist/runtime/src/guardrails/exceptions.js +49 -0
  49. package/dist/runtime/src/guardrails/secrets.js +97 -0
  50. package/dist/runtime/src/guardrails/types.js +9 -0
  51. package/dist/runtime/src/hooks/dispatch.js +78 -0
  52. package/dist/runtime/src/hooks/events.js +1 -0
  53. package/dist/runtime/src/hooks/hook-entry.js +19 -0
  54. package/dist/runtime/src/hooks/normalize.js +59 -0
  55. package/dist/runtime/src/hooks/output.js +12 -0
  56. package/dist/runtime/src/hooks/shell.js +138 -0
  57. package/dist/runtime/src/hooks/stop-verify.js +70 -0
  58. package/dist/runtime/src/install/apply.js +70 -0
  59. package/dist/runtime/src/install/doctor.js +196 -0
  60. package/dist/runtime/src/install/harness.js +87 -0
  61. package/dist/runtime/src/install/ownership.js +84 -0
  62. package/dist/runtime/src/install/plan.js +257 -0
  63. package/dist/runtime/src/install/profiles.js +28 -0
  64. package/dist/runtime/src/install/types.js +1 -0
  65. package/dist/runtime/src/install/uninstall.js +206 -0
  66. package/dist/runtime/src/install/update.js +123 -0
  67. package/dist/runtime/src/logging/local-log.js +158 -0
  68. package/dist/runtime/src/registry/npm.js +141 -0
  69. package/dist/runtime/src/review/claude-runner.js +4 -0
  70. package/dist/runtime/src/review/codex-runner.js +4 -0
  71. package/dist/runtime/src/review/packet.js +10 -0
  72. package/dist/runtime/src/review/result.js +24 -0
  73. package/dist/runtime/src/review/roles.js +3 -0
  74. package/dist/runtime/src/review/runner.js +45 -0
  75. package/dist/runtime/src/schema/validate.js +584 -0
  76. package/dist/runtime/src/security/permissions.js +654 -0
  77. package/dist/runtime/src/security/redact.js +41 -0
  78. package/dist/runtime/src/security/trust.js +209 -0
  79. package/dist/runtime/src/task/render.js +43 -0
  80. package/dist/runtime/src/task/service.js +235 -0
  81. package/dist/runtime/src/task/store.js +265 -0
  82. package/dist/runtime/src/verify/change-surface.js +86 -0
  83. package/dist/runtime/src/verify/evidence.js +89 -0
  84. package/dist/runtime/src/verify/fingerprint.js +67 -0
  85. package/dist/runtime/src/verify/scope.js +69 -0
  86. package/dist/runtime/src/verify/service.js +217 -0
  87. package/dist/runtime/src/verify/spawn.js +326 -0
  88. package/dist/runtime/src/verify/test-count.js +148 -0
  89. package/docs/en/spec/README.md +13 -0
  90. package/docs/en/spec/acceptance-and-evidence.md +21 -0
  91. package/docs/en/spec/delegation.md +21 -0
  92. package/docs/en/spec/guardrails.md +21 -0
  93. package/docs/en/spec/harness-adapters.md +21 -0
  94. package/docs/en/spec/judgment.md +21 -0
  95. package/docs/en/spec/loop-engineering.md +23 -0
  96. package/docs/en/spec/maintenance.md +21 -0
  97. package/docs/en/spec/review.md +21 -0
  98. package/docs/en/spec/troubleshooting.md +21 -0
  99. package/docs/zh-TW/spec/README.md +13 -0
  100. package/docs/zh-TW/spec/acceptance-and-evidence.md +23 -0
  101. package/docs/zh-TW/spec/delegation.md +23 -0
  102. package/docs/zh-TW/spec/guardrails.md +23 -0
  103. package/docs/zh-TW/spec/harness-adapters.md +23 -0
  104. package/docs/zh-TW/spec/judgment.md +23 -0
  105. package/docs/zh-TW/spec/loop-engineering.md +23 -0
  106. package/docs/zh-TW/spec/maintenance.md +23 -0
  107. package/docs/zh-TW/spec/review.md +23 -0
  108. package/docs/zh-TW/spec/troubleshooting.md +23 -0
  109. package/package.json +41 -0
  110. package/schemas/config.schema.json +231 -0
  111. package/schemas/evidence.schema.json +115 -0
  112. package/schemas/manifest.schema.json +116 -0
  113. package/schemas/task.schema.json +59 -0
  114. package/templates/common/AGENTS.block.md +3 -0
  115. package/templates/common/CLAUDE.block.md +3 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kyle Cheng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # Loop Engineering Toolkit
2
+
3
+ Loop Engineering Toolkit is an evidence-driven development-loop toolkit for
4
+ Codex and Claude Code. It is designed to turn acceptance criteria, explicit
5
+ verification, safe lifecycle hooks, and independent review into a repeatable
6
+ engineering workflow.
7
+
8
+ This repository is in its foundation stage. The CLI, hook runtime, normative
9
+ specification, and installation profiles are being developed in a reviewable
10
+ feature branch before the first pre-1.0 release.
11
+
12
+ The current CLI is an unreleased development interface. Its packed artifact is
13
+ checked by `npm run package:check`; command behavior may change before the first
14
+ tagged pre-1.0 release.
15
+
16
+ ## Quick start from a source checkout
17
+
18
+ Version 0.1.0 is prepared for release but has not yet been published to npm.
19
+ Until the protected release workflow completes, use a source checkout:
20
+
21
+ ```bash
22
+ git clone https://github.com/kylecheng3146/agent-ops.git
23
+ cd agent-ops
24
+ npm ci
25
+ npm run build
26
+ node dist/packages/cli/src/bin.js --version
27
+ ```
28
+
29
+ Preview a project installation before changing files:
30
+
31
+ ```bash
32
+ node dist/packages/cli/src/bin.js init \
33
+ --dry-run --scope project --harness both --profile core --json
34
+ ```
35
+
36
+ After reviewing the plan, apply it explicitly with `--yes`. Trust, diagnostics,
37
+ updates, and removal are separate commands:
38
+
39
+ ```bash
40
+ node dist/packages/cli/src/bin.js init --scope project --harness both --profile core --yes
41
+ node dist/packages/cli/src/bin.js trust status --json
42
+ node dist/packages/cli/src/bin.js doctor --json
43
+ node dist/packages/cli/src/bin.js update --target-version 0.1.0 --dry-run --json
44
+ node dist/packages/cli/src/bin.js uninstall --dry-run --json
45
+ ```
46
+
47
+ The commands after `init --yes` are post-apply operations; `doctor` may report
48
+ an unknown probe status until a repository-specific verification setup exists.
49
+
50
+ Use `--scope user` with user-home installations. Do not install from npm until
51
+ the `v0.1.0` tag has been published; the release workflow is the source of the
52
+ published package and provenance record.
53
+
54
+ ## Project principles
55
+
56
+ - Define verifiable success before making changes.
57
+ - Treat command output and current filesystem state as evidence.
58
+ - Keep advisory automation separate from blocking guardrails.
59
+ - Preserve user configuration through managed, reversible updates.
60
+ - Support Codex and Claude Code without project-specific assumptions.
61
+ - Collect no network telemetry.
62
+
63
+ ## Project status
64
+
65
+ No npm package has been published yet. Do not depend on the current repository
66
+ as a stable interface until a tagged release is available.
67
+
68
+ Documentation:
69
+
70
+ - [English specification](docs/en/spec/README.md)
71
+ - [繁體中文規範](docs/zh-TW/spec/README.md)
72
+ - [English guides](docs/en/guides/quickstart.md)
73
+ - [繁體中文指南](docs/zh-TW/guides/quickstart.md)
74
+
75
+ ## Community
76
+
77
+ - Read [CONTRIBUTING.md](CONTRIBUTING.md) before proposing a change.
78
+ - Report security issues according to [SECURITY.md](SECURITY.md).
79
+ - Participation is governed by [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
80
+
81
+ ## License
82
+
83
+ Copyright (c) 2026 Kyle Cheng. Released under the [MIT License](LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,22 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ The project has not published a supported release yet. Development branches
6
+ and pre-1.0 artifacts are provided for evaluation and do not carry an SLA.
7
+ Supported release lines and security-fix policy will be listed before version
8
+ 1.0.0.
9
+
10
+ ## Reporting a vulnerability
11
+
12
+ Do not disclose suspected vulnerabilities in a public issue. Use GitHub's
13
+ private vulnerability reporting interface for this repository when available.
14
+ If that interface is unavailable, contact the maintainer through the public
15
+ contact method listed on the
16
+ [kylecheng3146 GitHub profile](https://github.com/kylecheng3146) and request a
17
+ private reporting channel. Do not include exploit details in the initial public
18
+ message.
19
+
20
+ Reports should include the affected version, impact, minimal reproduction, and
21
+ any known mitigation. No response-time or remediation SLA is currently
22
+ promised.
@@ -0,0 +1,322 @@
1
+ export const COMMAND_NAMES = [
2
+ "init",
3
+ "config",
4
+ "trust",
5
+ "doctor",
6
+ "update",
7
+ "uninstall",
8
+ "task",
9
+ "verify",
10
+ "review"
11
+ ];
12
+ const COMMAND_SET = new Set(COMMAND_NAMES);
13
+ const SCOPES = new Set(["project", "user"]);
14
+ const HARNESSES = new Set(["both", "claude", "codex"]);
15
+ const PROFILES = new Set(["advisory", "core", "guardrails"]);
16
+ export class CliArgumentError extends Error {
17
+ code;
18
+ option;
19
+ constructor(code, message, option) {
20
+ super(message);
21
+ this.name = "CliArgumentError";
22
+ this.code = code;
23
+ this.option = option;
24
+ }
25
+ }
26
+ function readOptionValue(argv, index, option) {
27
+ const value = argv[index + 1];
28
+ if (value === undefined || value.startsWith("--")) {
29
+ throw new CliArgumentError("CLI_MISSING_VALUE", `${option} requires a value.`, option);
30
+ }
31
+ return value;
32
+ }
33
+ function duplicate(option) {
34
+ throw new CliArgumentError("CLI_DUPLICATE_OPTION", `${option} may not be repeated.`, option);
35
+ }
36
+ function invalidValue(option, value) {
37
+ throw new CliArgumentError("CLI_INVALID_VALUE", `Invalid value for ${option}: ${value}`, option);
38
+ }
39
+ export function parseArgs(argv) {
40
+ let command;
41
+ let action;
42
+ let scope;
43
+ let harness;
44
+ let taskId;
45
+ let targetVersion;
46
+ let title;
47
+ let sessionId;
48
+ const profiles = [];
49
+ const criteria = [];
50
+ const evidence = [];
51
+ let dryRun = false;
52
+ let json = false;
53
+ let yes = false;
54
+ let helpSeen = false;
55
+ let versionSeen = false;
56
+ for (let index = 0; index < argv.length; index += 1) {
57
+ const token = argv[index];
58
+ if (token === undefined) {
59
+ break;
60
+ }
61
+ switch (token) {
62
+ case "--scope": {
63
+ if (scope !== undefined) {
64
+ duplicate(token);
65
+ }
66
+ const value = readOptionValue(argv, index, token);
67
+ if (!SCOPES.has(value)) {
68
+ invalidValue(token, value);
69
+ }
70
+ scope = value;
71
+ index += 1;
72
+ break;
73
+ }
74
+ case "--harness": {
75
+ if (harness !== undefined) {
76
+ duplicate(token);
77
+ }
78
+ const value = readOptionValue(argv, index, token);
79
+ if (!HARNESSES.has(value)) {
80
+ invalidValue(token, value);
81
+ }
82
+ harness = value;
83
+ index += 1;
84
+ break;
85
+ }
86
+ case "--profile": {
87
+ const value = readOptionValue(argv, index, token);
88
+ if (!PROFILES.has(value)) {
89
+ invalidValue(token, value);
90
+ }
91
+ if (profiles.includes(value)) {
92
+ duplicate(`${token} ${value}`);
93
+ }
94
+ profiles.push(value);
95
+ index += 1;
96
+ break;
97
+ }
98
+ case "--task": {
99
+ if (taskId !== undefined) {
100
+ duplicate(token);
101
+ }
102
+ taskId = readOptionValue(argv, index, token);
103
+ index += 1;
104
+ break;
105
+ }
106
+ case "--target-version": {
107
+ if (targetVersion !== undefined) {
108
+ duplicate(token);
109
+ }
110
+ targetVersion = readOptionValue(argv, index, token);
111
+ index += 1;
112
+ break;
113
+ }
114
+ case "--title": {
115
+ if (title !== undefined) {
116
+ duplicate(token);
117
+ }
118
+ title = readOptionValue(argv, index, token);
119
+ index += 1;
120
+ break;
121
+ }
122
+ case "--criterion": {
123
+ criteria.push(readOptionValue(argv, index, token));
124
+ index += 1;
125
+ break;
126
+ }
127
+ case "--evidence": {
128
+ evidence.push(readOptionValue(argv, index, token));
129
+ index += 1;
130
+ break;
131
+ }
132
+ case "--session": {
133
+ if (sessionId !== undefined) {
134
+ duplicate(token);
135
+ }
136
+ sessionId = readOptionValue(argv, index, token);
137
+ index += 1;
138
+ break;
139
+ }
140
+ case "--dry-run":
141
+ if (dryRun) {
142
+ duplicate(token);
143
+ }
144
+ dryRun = true;
145
+ break;
146
+ case "--json":
147
+ if (json) {
148
+ duplicate(token);
149
+ }
150
+ json = true;
151
+ break;
152
+ case "--yes":
153
+ if (yes) {
154
+ duplicate(token);
155
+ }
156
+ yes = true;
157
+ break;
158
+ case "--help":
159
+ case "-h":
160
+ if (helpSeen) {
161
+ duplicate(token);
162
+ }
163
+ helpSeen = true;
164
+ break;
165
+ case "--version":
166
+ case "-v":
167
+ if (versionSeen) {
168
+ duplicate(token);
169
+ }
170
+ versionSeen = true;
171
+ break;
172
+ default:
173
+ if (token.startsWith("-")) {
174
+ throw new CliArgumentError("CLI_UNKNOWN_OPTION", `Unknown option: ${token}`, token);
175
+ }
176
+ if (command === "config" &&
177
+ action === undefined &&
178
+ token === "explain") {
179
+ action = token;
180
+ break;
181
+ }
182
+ if (command === "trust" &&
183
+ action === undefined &&
184
+ ["grant", "revoke", "status"].includes(token)) {
185
+ action = token;
186
+ break;
187
+ }
188
+ if (command === "task" &&
189
+ action === undefined &&
190
+ [
191
+ "archive",
192
+ "attach",
193
+ "complete",
194
+ "create",
195
+ "export",
196
+ "status"
197
+ ].includes(token)) {
198
+ action = token;
199
+ break;
200
+ }
201
+ if (command !== undefined) {
202
+ throw new CliArgumentError("CLI_UNEXPECTED_ARGUMENT", `Unexpected argument: ${token}`);
203
+ }
204
+ if (!COMMAND_SET.has(token)) {
205
+ throw new CliArgumentError("CLI_UNKNOWN_COMMAND", `Unknown command: ${token}`);
206
+ }
207
+ command = token;
208
+ }
209
+ }
210
+ if (helpSeen && versionSeen) {
211
+ throw new CliArgumentError("CLI_CONFLICTING_ACTION", "--help and --version cannot be combined.");
212
+ }
213
+ if ((helpSeen || versionSeen) && command !== undefined) {
214
+ throw new CliArgumentError("CLI_CONFLICTING_ACTION", "Global help or version cannot be combined with a command.");
215
+ }
216
+ if (helpSeen || versionSeen) {
217
+ if (scope !== undefined ||
218
+ harness !== undefined ||
219
+ profiles.length > 0 ||
220
+ taskId !== undefined ||
221
+ targetVersion !== undefined ||
222
+ title !== undefined ||
223
+ criteria.length > 0 ||
224
+ evidence.length > 0 ||
225
+ sessionId !== undefined ||
226
+ dryRun ||
227
+ yes) {
228
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "Only --json may be combined with global help or version.");
229
+ }
230
+ command = helpSeen ? "help" : "version";
231
+ }
232
+ if (command === undefined) {
233
+ throw new CliArgumentError("CLI_COMMAND_REQUIRED", "A command, --help, or --version is required.");
234
+ }
235
+ if (command === "trust" && action === undefined) {
236
+ throw new CliArgumentError("CLI_ACTION_REQUIRED", "The trust command requires one of: status, grant, revoke.");
237
+ }
238
+ if (command === "task" && action === undefined) {
239
+ throw new CliArgumentError("CLI_ACTION_REQUIRED", "The task command requires one of: create, status, attach, complete, archive, export.");
240
+ }
241
+ const hasTaskTargetOptions = taskId !== undefined ||
242
+ sessionId !== undefined;
243
+ const hasTaskMutationOptions = title !== undefined ||
244
+ criteria.length > 0 ||
245
+ evidence.length > 0;
246
+ if (command !== "task" &&
247
+ command !== "verify" &&
248
+ command !== "review" &&
249
+ (hasTaskTargetOptions || hasTaskMutationOptions)) {
250
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "Task target options may be used only with task or verify.");
251
+ }
252
+ if (command !== "update" && targetVersion !== undefined) {
253
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "--target-version may be used only with update.");
254
+ }
255
+ if (command === "task") {
256
+ if (harness !== undefined ||
257
+ profiles.length > 0 ||
258
+ dryRun ||
259
+ yes) {
260
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "Task commands do not accept harness, profile, dry-run, or yes options.");
261
+ }
262
+ const taskOptionInvalid = (action === "create" &&
263
+ (taskId !== undefined ||
264
+ evidence.length > 0 ||
265
+ sessionId !== undefined)) ||
266
+ (action === "status" &&
267
+ (title !== undefined ||
268
+ criteria.length > 0 ||
269
+ evidence.length > 0 ||
270
+ (taskId !== undefined && sessionId !== undefined))) ||
271
+ (action === "attach" &&
272
+ (title !== undefined ||
273
+ criteria.length > 0 ||
274
+ evidence.length > 0)) ||
275
+ (action === "complete" &&
276
+ (title !== undefined ||
277
+ criteria.length > 0 ||
278
+ sessionId !== undefined)) ||
279
+ ((action === "archive" || action === "export") &&
280
+ (title !== undefined ||
281
+ criteria.length > 0 ||
282
+ evidence.length > 0 ||
283
+ sessionId !== undefined));
284
+ if (taskOptionInvalid) {
285
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", `Unsupported option for task ${action}.`);
286
+ }
287
+ }
288
+ if (command === "verify" &&
289
+ (harness !== undefined ||
290
+ profiles.length > 0 ||
291
+ title !== undefined ||
292
+ criteria.length > 0 ||
293
+ evidence.length > 0 ||
294
+ dryRun ||
295
+ yes ||
296
+ (taskId !== undefined && sessionId !== undefined))) {
297
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "Verify accepts only scope, task or session, and json options.");
298
+ }
299
+ if (command === "review" &&
300
+ (title !== undefined || sessionId !== undefined)) {
301
+ throw new CliArgumentError("CLI_OPTION_NOT_ALLOWED", "Review accepts harness, criteria, evidence, scope, dry-run, json, and yes options.");
302
+ }
303
+ if (command === "review" && harness === "both") {
304
+ invalidValue("--harness", harness);
305
+ }
306
+ return {
307
+ command,
308
+ ...(action === undefined ? {} : { action }),
309
+ ...(scope === undefined ? {} : { scope }),
310
+ ...(harness === undefined ? {} : { harness }),
311
+ profiles,
312
+ ...(taskId === undefined ? {} : { taskId }),
313
+ ...(targetVersion === undefined ? {} : { targetVersion }),
314
+ ...(title === undefined ? {} : { title }),
315
+ ...(criteria.length === 0 ? {} : { criteria }),
316
+ ...(evidence.length === 0 ? {} : { evidence }),
317
+ ...(sessionId === undefined ? {} : { sessionId }),
318
+ dryRun,
319
+ json,
320
+ yes
321
+ };
322
+ }