@kylecheng3146/agent-ops 0.5.3 → 0.6.0

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 (93) hide show
  1. package/README.md +48 -0
  2. package/dist/packages/cli/src/args.js +165 -2
  3. package/dist/packages/cli/src/bin.js +64 -17
  4. package/dist/packages/cli/src/cli.js +33 -6
  5. package/dist/packages/cli/src/commands/advance.js +23 -3
  6. package/dist/packages/cli/src/commands/review-show.js +1 -1
  7. package/dist/packages/cli/src/commands/review.js +100 -9
  8. package/dist/packages/cli/src/commands/run.js +111 -0
  9. package/dist/packages/cli/src/commands/task.js +61 -17
  10. package/dist/packages/cli/src/commands/verify.js +1 -0
  11. package/dist/packages/cli/src/context.js +63 -1
  12. package/dist/packages/cli/src/hook-process.js +31 -1
  13. package/dist/packages/cli/src/owned-run-step.js +65 -0
  14. package/dist/packages/cli/src/parallel-deps.js +18 -5
  15. package/dist/packages/cli/src/run-deps.js +314 -0
  16. package/dist/packages/cli/src/run-entry.js +943 -0
  17. package/dist/packages/cli/src/run-setup-entry.js +32 -0
  18. package/dist/packages/cli/src/run-step-entry.js +58 -0
  19. package/dist/runtime/src/config/explain.js +6 -0
  20. package/dist/runtime/src/config/hash.js +1 -1
  21. package/dist/runtime/src/config/merge.js +9 -1
  22. package/dist/runtime/src/contracts.js +2 -2
  23. package/dist/runtime/src/hooks/completion-gate.js +8 -2
  24. package/dist/runtime/src/install/doctor.js +2 -0
  25. package/dist/runtime/src/parallel/finish.js +85 -22
  26. package/dist/runtime/src/parallel/guard.js +5 -1
  27. package/dist/runtime/src/parallel/integrate.js +288 -10
  28. package/dist/runtime/src/parallel/manage.js +4 -1
  29. package/dist/runtime/src/parallel/receipt.js +71 -5
  30. package/dist/runtime/src/parallel/service.js +41 -1
  31. package/dist/runtime/src/review/attestation.js +36 -11
  32. package/dist/runtime/src/review/execute.js +24 -1
  33. package/dist/runtime/src/review/packet.js +35 -1
  34. package/dist/runtime/src/review/runner.js +12 -1
  35. package/dist/runtime/src/review/scope.js +18 -1
  36. package/dist/runtime/src/review/slots.js +35 -10
  37. package/dist/runtime/src/run/authorization.js +60 -0
  38. package/dist/runtime/src/run/budget.js +30 -0
  39. package/dist/runtime/src/run/controls.js +139 -0
  40. package/dist/runtime/src/run/convergence.js +177 -0
  41. package/dist/runtime/src/run/hosts/claude.js +180 -0
  42. package/dist/runtime/src/run/hosts/codex.js +279 -0
  43. package/dist/runtime/src/run/hosts/index.js +4 -0
  44. package/dist/runtime/src/run/hosts/protocol.js +254 -0
  45. package/dist/runtime/src/run/hosts/types.js +1 -0
  46. package/dist/runtime/src/run/hosts/util.js +136 -0
  47. package/dist/runtime/src/run/integration.js +204 -0
  48. package/dist/runtime/src/run/macOS.js +189 -0
  49. package/dist/runtime/src/run/ownership.js +22 -0
  50. package/dist/runtime/src/run/planning.js +25 -0
  51. package/dist/runtime/src/run/policy-transition.js +1076 -0
  52. package/dist/runtime/src/run/policy.js +176 -0
  53. package/dist/runtime/src/run/ratchet.js +71 -0
  54. package/dist/runtime/src/run/scheduler.js +260 -0
  55. package/dist/runtime/src/run/service.js +425 -0
  56. package/dist/runtime/src/run/supervisor.js +635 -0
  57. package/dist/runtime/src/run/transport.js +159 -0
  58. package/dist/runtime/src/run/types.js +1 -0
  59. package/dist/runtime/src/run/usage.js +81 -0
  60. package/dist/runtime/src/run/verification.js +64 -0
  61. package/dist/runtime/src/run/worker-gate.js +48 -0
  62. package/dist/runtime/src/schema/acceptance.js +91 -0
  63. package/dist/runtime/src/schema/validate.js +67 -7
  64. package/dist/runtime/src/task/completion.js +14 -2
  65. package/dist/runtime/src/task/contract.js +17 -0
  66. package/dist/runtime/src/task/pin-finding.js +81 -0
  67. package/dist/runtime/src/task/service.js +316 -13
  68. package/dist/runtime/src/task/store.js +57 -7
  69. package/dist/runtime/src/verify/acceptance-coverage.js +85 -0
  70. package/dist/runtime/src/verify/acceptance-protocol.js +252 -0
  71. package/dist/runtime/src/verify/acceptance-replay.js +239 -0
  72. package/dist/runtime/src/verify/adapters/index.js +5 -0
  73. package/dist/runtime/src/verify/adapters/jest.js +142 -0
  74. package/dist/runtime/src/verify/adapters/node-reporter.js +20 -0
  75. package/dist/runtime/src/verify/adapters/node.js +254 -0
  76. package/dist/runtime/src/verify/adapters/pytest.js +188 -0
  77. package/dist/runtime/src/verify/adapters/rust.js +84 -0
  78. package/dist/runtime/src/verify/adapters/shared.js +82 -0
  79. package/dist/runtime/src/verify/adapters/vitest.js +218 -0
  80. package/dist/runtime/src/verify/evidence.js +5 -2
  81. package/dist/runtime/src/verify/service.js +24 -8
  82. package/dist/runtime/src/verify/source-fingerprint.js +1 -1
  83. package/dist/runtime/src/verify/spawn.js +13 -2
  84. package/docs/en/spec/acceptance-and-evidence.md +48 -0
  85. package/docs/en/spec/loop-engineering.md +49 -0
  86. package/docs/zh-TW/spec/acceptance-and-evidence.md +21 -1
  87. package/docs/zh-TW/spec/loop-engineering.md +22 -0
  88. package/package.json +1 -1
  89. package/schemas/config.schema.json +221 -19
  90. package/schemas/evidence.schema.json +129 -6
  91. package/schemas/task.schema.json +265 -6
  92. package/templates/acceptance/agent_ops_acceptance.rs +36 -0
  93. package/templates/acceptance/agent_ops_pytest.py +46 -0
@@ -4,10 +4,18 @@
4
4
  "title": "Agent Ops task",
5
5
  "type": "object",
6
6
  "additionalProperties": false,
7
- "required": ["schemaVersion", "id", "title", "criteria"],
7
+ "required": [
8
+ "schemaVersion",
9
+ "id",
10
+ "title",
11
+ "criteria"
12
+ ],
8
13
  "properties": {
9
14
  "schemaVersion": {
10
- "const": 1
15
+ "enum": [
16
+ 1,
17
+ 2
18
+ ]
11
19
  },
12
20
  "id": {
13
21
  "$ref": "#/$defs/id"
@@ -28,7 +36,11 @@
28
36
  "items": {
29
37
  "type": "object",
30
38
  "additionalProperties": false,
31
- "required": ["id", "description", "verifierIds"],
39
+ "required": [
40
+ "id",
41
+ "description",
42
+ "verifierIds"
43
+ ],
32
44
  "properties": {
33
45
  "id": {
34
46
  "$ref": "#/$defs/id"
@@ -38,14 +50,232 @@
38
50
  },
39
51
  "verifierIds": {
40
52
  "type": "array",
41
- "minItems": 1,
53
+ "minItems": 0,
42
54
  "uniqueItems": true,
43
55
  "items": {
44
56
  "$ref": "#/$defs/id"
45
57
  }
58
+ },
59
+ "acceptance": {
60
+ "type": "object",
61
+ "additionalProperties": false,
62
+ "required": [
63
+ "mode",
64
+ "baselineCommit",
65
+ "bindings"
66
+ ],
67
+ "properties": {
68
+ "mode": {
69
+ "enum": [
70
+ "behavioral",
71
+ "invariant",
72
+ "review-only"
73
+ ]
74
+ },
75
+ "baselineCommit": {
76
+ "type": "string",
77
+ "pattern": "^(?:[a-f0-9]{40}|[a-f0-9]{64})$"
78
+ },
79
+ "reviewOnlyReason": {
80
+ "type": "string",
81
+ "minLength": 1,
82
+ "maxLength": 4096,
83
+ "pattern": "\\S"
84
+ },
85
+ "bindings": {
86
+ "type": "array",
87
+ "maxItems": 64,
88
+ "items": {
89
+ "type": "object",
90
+ "additionalProperties": false,
91
+ "required": [
92
+ "runnerId",
93
+ "checkIds",
94
+ "materials"
95
+ ],
96
+ "properties": {
97
+ "runnerId": {
98
+ "$ref": "#/$defs/id"
99
+ },
100
+ "checkIds": {
101
+ "type": "array",
102
+ "maxItems": 512,
103
+ "uniqueItems": true,
104
+ "items": {
105
+ "type": "string",
106
+ "minLength": 1
107
+ },
108
+ "minItems": 1
109
+ },
110
+ "redCheckIds": {
111
+ "type": "array",
112
+ "maxItems": 512,
113
+ "uniqueItems": true,
114
+ "items": {
115
+ "type": "string",
116
+ "minLength": 1
117
+ }
118
+ },
119
+ "materials": {
120
+ "type": "array",
121
+ "minItems": 1,
122
+ "maxItems": 512,
123
+ "items": {
124
+ "type": "object",
125
+ "additionalProperties": false,
126
+ "required": [
127
+ "path",
128
+ "role"
129
+ ],
130
+ "properties": {
131
+ "path": {
132
+ "type": "string",
133
+ "minLength": 1,
134
+ "maxLength": 4096,
135
+ "pattern": "^[^/\\\\\\u0000]+(?:/[^/\\\\\\u0000]+)*$",
136
+ "not": {
137
+ "anyOf": [
138
+ {
139
+ "pattern": "(?:^|/)(?:\\.{1,2}|\\.git|\\.agent-ops|node_modules)(?:/|$)"
140
+ },
141
+ {
142
+ "pattern": "^(?:dist|build|\\.tmp)/"
143
+ },
144
+ {
145
+ "enum": [
146
+ "package.json",
147
+ "package-lock.json",
148
+ "pnpm-lock.yaml",
149
+ "yarn.lock",
150
+ "Cargo.toml",
151
+ "Cargo.lock",
152
+ "pyproject.toml"
153
+ ]
154
+ }
155
+ ]
156
+ }
157
+ },
158
+ "role": {
159
+ "enum": [
160
+ "test",
161
+ "fixture",
162
+ "helper"
163
+ ]
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ },
172
+ "allOf": [
173
+ {
174
+ "if": {
175
+ "properties": {
176
+ "mode": {
177
+ "const": "review-only"
178
+ }
179
+ },
180
+ "type": "object"
181
+ },
182
+ "then": {
183
+ "required": ["reviewOnlyReason"],
184
+ "properties": {
185
+ "reviewOnlyReason": {"type": "string"},
186
+ "bindings": {
187
+ "maxItems": 0,
188
+ "type": "array"
189
+ }
190
+ },
191
+ "type": "object"
192
+ },
193
+ "else": {
194
+ "properties": {
195
+ "reviewOnlyReason": false,
196
+ "bindings": {
197
+ "minItems": 1,
198
+ "type": "array"
199
+ }
200
+ },
201
+ "type": "object"
202
+ }
203
+ }
204
+ ]
205
+ },
206
+ "finding": {
207
+ "type": "object",
208
+ "additionalProperties": false,
209
+ "required": [
210
+ "pinId",
211
+ "reportDigest",
212
+ "findingIndex",
213
+ "candidateCommit",
214
+ "criterionIds"
215
+ ],
216
+ "properties": {
217
+ "pinId": {
218
+ "type": "string",
219
+ "pattern": "^[a-f0-9]{64}$"
220
+ },
221
+ "reportDigest": {
222
+ "type": "string",
223
+ "pattern": "^[a-f0-9]{64}$"
224
+ },
225
+ "findingIndex": {
226
+ "type": "integer",
227
+ "minimum": 0
228
+ },
229
+ "candidateCommit": {
230
+ "type": "string",
231
+ "pattern": "^(?:[a-f0-9]{40}|[a-f0-9]{64})$"
232
+ },
233
+ "criterionIds": {
234
+ "type": "array",
235
+ "maxItems": 512,
236
+ "uniqueItems": true,
237
+ "items": {
238
+ "type": "string",
239
+ "minLength": 1
240
+ }
241
+ }
242
+ }
243
+ }
244
+ },
245
+ "allOf": [
246
+ {
247
+ "if": {
248
+ "not": {
249
+ "required": [
250
+ "acceptance"
251
+ ],
252
+ "properties": {
253
+ "acceptance": {}
254
+ },
255
+ "type": "object"
256
+ }
257
+ },
258
+ "then": {
259
+ "properties": {
260
+ "verifierIds": {
261
+ "minItems": 1,
262
+ "type": "array"
263
+ }
264
+ },
265
+ "type": "object"
266
+ }
46
267
  }
47
- }
268
+ ]
48
269
  }
270
+ },
271
+ "goal": {
272
+ "type": "string",
273
+ "minLength": 1,
274
+ "maxLength": 65536
275
+ },
276
+ "contractRevision": {
277
+ "type": "integer",
278
+ "minimum": 0
49
279
  }
50
280
  },
51
281
  "$defs": {
@@ -61,5 +291,34 @@
61
291
  }
62
292
  }
63
293
  },
64
- "$comment": "Criterion ID uniqueness is a semantic constraint enforced by runtime validation."
294
+ "$comment": "Criterion ID uniqueness is a semantic constraint enforced by runtime validation.",
295
+ "allOf": [
296
+ {
297
+ "if": {
298
+ "properties": {
299
+ "schemaVersion": {
300
+ "const": 1
301
+ }
302
+ },
303
+ "type": "object"
304
+ },
305
+ "then": {
306
+ "properties": {
307
+ "goal": false,
308
+ "contractRevision": false,
309
+ "criteria": {
310
+ "items": {
311
+ "properties": {
312
+ "acceptance": false,
313
+ "finding": false
314
+ },
315
+ "type": "object"
316
+ },
317
+ "type": "array"
318
+ }
319
+ },
320
+ "type": "object"
321
+ }
322
+ }
323
+ ]
65
324
  }
@@ -0,0 +1,36 @@
1
+ //! Stable stdlib acceptance harness. Compile after the product build.
2
+ //! Tests return explicit assertion results; a panic is infrastructure UNKNOWN.
3
+ use std::io::{self, Write};
4
+ use std::panic::{catch_unwind, AssertUnwindSafe};
5
+
6
+ fn quoted(value: &str) -> String {
7
+ let mut out = String::from("\"");
8
+ for ch in value.chars() {
9
+ match ch {
10
+ '\\' => out.push_str("\\\\"),
11
+ '"' => out.push_str("\\\""),
12
+ c if (c as u32) < 32 => out.push_str(&format!("\\u{:04x}", c as u32)),
13
+ c => out.push(c),
14
+ }
15
+ }
16
+ out.push('"'); out
17
+ }
18
+
19
+ pub struct Harness { failed: bool }
20
+ impl Harness {
21
+ pub fn new() -> Self { Self { failed: false } }
22
+ pub fn check<F: FnOnce() -> Result<(), String>>(&mut self, id: &str, check: F) {
23
+ let (status, failure) = match catch_unwind(AssertUnwindSafe(check)) {
24
+ Ok(Ok(())) => ("PASS", "none"),
25
+ Ok(Err(_)) => { self.failed = true; ("FAIL", "assertion-failed") },
26
+ Err(_) => { self.failed = true; ("UNKNOWN", "infrastructure-error") },
27
+ };
28
+ println!("{{\"type\":\"check\",\"checkId\":{},\"status\":\"{}\",\"failureClass\":\"{}\",\"attempts\":1}}", quoted(id), status, failure);
29
+ io::stdout().flush().expect("acceptance output failed");
30
+ }
31
+ pub fn finish(self) -> ! {
32
+ println!("{{\"type\":\"completed\",\"completed\":true}}");
33
+ io::stdout().flush().expect("acceptance output failed");
34
+ std::process::exit(if self.failed { 1 } else { 0 });
35
+ }
36
+ }
@@ -0,0 +1,46 @@
1
+ """Load with pytest -p agent_ops_pytest -p no:terminal (PYTHONPATH points here).
2
+ Only AssertionError in a test call is behavioral red; fixture errors are not.
3
+ The product checkout supplies pytest and all dependencies.
4
+ """
5
+ import json
6
+ import os
7
+ import sys
8
+ import pytest
9
+
10
+
11
+ def emit(event):
12
+ event["executionId"] = os.environ.get("AGENT_OPS_ACCEPTANCE_EXECUTION_ID")
13
+ event["phase"] = os.environ.get("AGENT_OPS_ACCEPTANCE_PHASE")
14
+ sys.__stdout__.write(json.dumps(event, ensure_ascii=True) + "\n")
15
+ sys.__stdout__.flush()
16
+
17
+
18
+ @pytest.hookimpl(hookwrapper=True)
19
+ def pytest_runtest_makereport(item, call):
20
+ outcome = yield
21
+ report = outcome.get_result()
22
+ emit({"type": "test-report", "nodeid": report.nodeid,
23
+ "when": report.when, "outcome": report.outcome,
24
+ "assertion": call.excinfo is not None and call.excinfo.errisinstance(AssertionError),
25
+ "wasxfail": getattr(report, "wasxfail", False),
26
+ "attempts": int(getattr(report, "rerun", 0)) + 1})
27
+
28
+
29
+ def pytest_collectreport(report):
30
+ if report.failed:
31
+ emit({"type": "collection-error", "nodeid": report.nodeid})
32
+
33
+
34
+ def pytest_internalerror(excrepr, excinfo):
35
+ emit({"type": "internal-error"})
36
+
37
+
38
+ def pytest_sessionfinish(session, exitstatus):
39
+ if int(exitstatus) not in (0, 1):
40
+ emit({"type": "session-error", "exitstatus": int(exitstatus)})
41
+ emit({"type": "session-finished", "completed": True,
42
+ "exitstatus": int(exitstatus), "frameworkVersion": pytest.__version__})
43
+
44
+
45
+ if __name__ == "__main__":
46
+ raise SystemExit(pytest.main([*sys.argv[1:], "-p", "no:terminal", "--capture=sys"], plugins=[sys.modules[__name__]]))