@xiongxianfei/rigorloop 0.1.5 → 0.2.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.
- package/README.md +107 -2
- package/dist/bin/rigorloop.js +564 -165
- package/dist/lib/adapters.js +50 -0
- package/dist/lib/lockfile.js +196 -29
- package/dist/metadata/adapter-artifacts-v0.2.0.json +30 -0
- package/dist/metadata/releases.json +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const ADAPTERS = {
|
|
2
|
+
codex: {
|
|
3
|
+
name: "codex",
|
|
4
|
+
displayName: "Codex",
|
|
5
|
+
installRoots: {
|
|
6
|
+
skills: ".agents/skills",
|
|
7
|
+
},
|
|
8
|
+
directoryPlan: [".agents", ".agents/skills"],
|
|
9
|
+
},
|
|
10
|
+
claude: {
|
|
11
|
+
name: "claude",
|
|
12
|
+
displayName: "Claude Code",
|
|
13
|
+
installRoots: {
|
|
14
|
+
skills: ".claude/skills",
|
|
15
|
+
},
|
|
16
|
+
directoryPlan: [".claude", ".claude/skills"],
|
|
17
|
+
},
|
|
18
|
+
opencode: {
|
|
19
|
+
name: "opencode",
|
|
20
|
+
displayName: "opencode",
|
|
21
|
+
installRoots: {
|
|
22
|
+
skills: ".opencode/skills",
|
|
23
|
+
commands: ".opencode/commands",
|
|
24
|
+
},
|
|
25
|
+
directoryPlan: [".opencode", ".opencode/skills", ".opencode/commands"],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function cloneDescriptor(descriptor) {
|
|
30
|
+
return {
|
|
31
|
+
...descriptor,
|
|
32
|
+
installRoots: { ...descriptor.installRoots },
|
|
33
|
+
directoryPlan: [...descriptor.directoryPlan],
|
|
34
|
+
archiveName(releaseTag) {
|
|
35
|
+
return `rigorloop-adapter-${descriptor.name}-${releaseTag}.zip`;
|
|
36
|
+
},
|
|
37
|
+
primaryInstallRoot() {
|
|
38
|
+
return descriptor.installRoots.skills;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function adapterDescriptor(name) {
|
|
44
|
+
const descriptor = ADAPTERS[name];
|
|
45
|
+
return descriptor ? cloneDescriptor(descriptor) : undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function supportedAdapterNames() {
|
|
49
|
+
return Object.keys(ADAPTERS);
|
|
50
|
+
}
|
package/dist/lib/lockfile.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
|
|
3
3
|
const SHA256_PATTERN = /^[0-9a-f]{64}$/i;
|
|
4
4
|
const SUPPORTED_SOURCES = new Set(["release-archive", "local-archive"]);
|
|
5
|
+
const SUPPORTED_ADAPTERS = new Set(["codex", "claude", "opencode"]);
|
|
5
6
|
const TOP_LEVEL_FIELDS = ["schema_version", "rigorloop", "manifest", "generated"];
|
|
6
7
|
const RIGORLOOP_FIELDS = ["package", "version"];
|
|
7
8
|
const MANIFEST_FIELDS = ["path", "sha256"];
|
|
@@ -13,10 +14,20 @@ const ADAPTER_FIELDS = [
|
|
|
13
14
|
"archive",
|
|
14
15
|
"archive_sha256",
|
|
15
16
|
"installed_root",
|
|
17
|
+
"installed_roots",
|
|
16
18
|
"tree_hash_algorithm",
|
|
17
19
|
"tree_sha256",
|
|
18
20
|
"file_count",
|
|
21
|
+
"root_hashes",
|
|
19
22
|
];
|
|
23
|
+
const SINGLE_ROOTS = {
|
|
24
|
+
codex: ".agents/skills",
|
|
25
|
+
claude: ".claude/skills",
|
|
26
|
+
};
|
|
27
|
+
const OPENCODE_ROOTS = {
|
|
28
|
+
skills: ".opencode/skills",
|
|
29
|
+
commands: ".opencode/commands",
|
|
30
|
+
};
|
|
20
31
|
|
|
21
32
|
function failure(kind, code, message, path = "rigorloop.lock") {
|
|
22
33
|
return { ok: false, kind, code, message, path };
|
|
@@ -38,6 +49,11 @@ function isSha256(value) {
|
|
|
38
49
|
return typeof value === "string" && SHA256_PATTERN.test(value);
|
|
39
50
|
}
|
|
40
51
|
|
|
52
|
+
function isNonNegativeInteger(value) {
|
|
53
|
+
const text = String(value);
|
|
54
|
+
return /^\d+$/.test(text) && Number.isInteger(Number.parseInt(text, 10));
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
function parseTopLevel(lines) {
|
|
42
58
|
const sections = new Map();
|
|
43
59
|
for (const line of lines) {
|
|
@@ -63,6 +79,10 @@ function parseSection(lines, sectionName, allowedFields) {
|
|
|
63
79
|
if (line.trim() === "") {
|
|
64
80
|
continue;
|
|
65
81
|
}
|
|
82
|
+
const nestedMatch = line.match(/^ ([A-Za-z_][A-Za-z0-9_-]*):\s*$/);
|
|
83
|
+
if (nestedMatch) {
|
|
84
|
+
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported nested field ${sectionName}.${nestedMatch[1]}`);
|
|
85
|
+
}
|
|
66
86
|
const match = line.match(/^ ([A-Za-z_][A-Za-z0-9_-]*):(?:\s*(.*))?$/);
|
|
67
87
|
if (!match) {
|
|
68
88
|
continue;
|
|
@@ -112,6 +132,18 @@ function parseAdapters(lines) {
|
|
|
112
132
|
|
|
113
133
|
const adapters = [];
|
|
114
134
|
let current;
|
|
135
|
+
let nested;
|
|
136
|
+
let rootHashRole;
|
|
137
|
+
|
|
138
|
+
function pushCurrent() {
|
|
139
|
+
if (current) {
|
|
140
|
+
adapters.push(current);
|
|
141
|
+
}
|
|
142
|
+
current = undefined;
|
|
143
|
+
nested = undefined;
|
|
144
|
+
rootHashRole = undefined;
|
|
145
|
+
}
|
|
146
|
+
|
|
115
147
|
for (let index = adaptersStart + 1; index < lines.length; index += 1) {
|
|
116
148
|
const line = lines[index];
|
|
117
149
|
if (/^[A-Za-z_][A-Za-z0-9_-]*:/.test(line)) {
|
|
@@ -124,11 +156,10 @@ function parseAdapters(lines) {
|
|
|
124
156
|
if (generatedFieldMatch) {
|
|
125
157
|
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported field generated.${generatedFieldMatch[1]}`);
|
|
126
158
|
}
|
|
159
|
+
|
|
127
160
|
const startMatch = line.match(/^ - ([A-Za-z_][A-Za-z0-9_-]*):(?:\s*(.*))?$/);
|
|
128
161
|
if (startMatch) {
|
|
129
|
-
|
|
130
|
-
adapters.push(current);
|
|
131
|
-
}
|
|
162
|
+
pushCurrent();
|
|
132
163
|
current = {};
|
|
133
164
|
const [, key, value] = startMatch;
|
|
134
165
|
if (!ADAPTER_FIELDS.includes(key)) {
|
|
@@ -147,26 +178,146 @@ function parseAdapters(lines) {
|
|
|
147
178
|
if (!ADAPTER_FIELDS.includes(key)) {
|
|
148
179
|
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported field generated.adapters[${adapters.length}].${key}`);
|
|
149
180
|
}
|
|
181
|
+
if (key === "installed_roots" || key === "root_hashes") {
|
|
182
|
+
if (value !== undefined && value !== "") {
|
|
183
|
+
return failure("invalid", "invalid-lockfile", `Expected mapping for generated.adapters[${adapters.length}].${key}`);
|
|
184
|
+
}
|
|
185
|
+
current[key] = {};
|
|
186
|
+
nested = key;
|
|
187
|
+
rootHashRole = undefined;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
150
190
|
if (value === undefined || value === "") {
|
|
151
191
|
return failure("invalid", "invalid-lockfile", `Missing scalar value for generated.adapters[${adapters.length}].${key}`);
|
|
152
192
|
}
|
|
153
193
|
current[key] = parseScalar(value);
|
|
194
|
+
nested = undefined;
|
|
195
|
+
rootHashRole = undefined;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const installedRootMatch = line.match(/^ ([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
200
|
+
if (installedRootMatch && current && nested === "installed_roots") {
|
|
201
|
+
current.installed_roots[installedRootMatch[1]] = parseScalar(installedRootMatch[2]);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const rootHashRoleMatch = line.match(/^ ([A-Za-z_][A-Za-z0-9_-]*):\s*$/);
|
|
206
|
+
if (rootHashRoleMatch && current && nested === "root_hashes") {
|
|
207
|
+
rootHashRole = rootHashRoleMatch[1];
|
|
208
|
+
current.root_hashes[rootHashRole] = {};
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const rootHashFieldMatch = line.match(/^ ([A-Za-z_][A-Za-z0-9_-]*):\s*(.*)$/);
|
|
213
|
+
if (rootHashFieldMatch && current && nested === "root_hashes" && rootHashRole) {
|
|
214
|
+
const [, key, value] = rootHashFieldMatch;
|
|
215
|
+
if (!["tree_sha256", "file_count"].includes(key)) {
|
|
216
|
+
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported field generated.adapters[${adapters.length}].root_hashes.${rootHashRole}.${key}`);
|
|
217
|
+
}
|
|
218
|
+
current.root_hashes[rootHashRole][key] = key === "file_count" ? Number.parseInt(parseScalar(value), 10) : parseScalar(value);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (line.startsWith(" ") && current) {
|
|
223
|
+
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported lockfile adapter mapping near: ${line.trim()}`);
|
|
154
224
|
}
|
|
155
225
|
}
|
|
156
|
-
|
|
157
|
-
adapters.push(current);
|
|
158
|
-
}
|
|
226
|
+
pushCurrent();
|
|
159
227
|
return { adapters };
|
|
160
228
|
}
|
|
161
229
|
|
|
162
|
-
function
|
|
163
|
-
|
|
230
|
+
function unexpectedFields(adapter, allowed) {
|
|
231
|
+
return Object.keys(adapter).filter((field) => !allowed.includes(field));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function validateSingleRootAdapter(adapter, schemaVersion) {
|
|
235
|
+
const allowed = [
|
|
236
|
+
"adapter",
|
|
237
|
+
"release",
|
|
238
|
+
"source",
|
|
239
|
+
"archive",
|
|
240
|
+
"archive_sha256",
|
|
241
|
+
"installed_root",
|
|
242
|
+
"tree_hash_algorithm",
|
|
243
|
+
"tree_sha256",
|
|
244
|
+
"file_count",
|
|
245
|
+
];
|
|
246
|
+
const unexpected = unexpectedFields(adapter, allowed);
|
|
247
|
+
if (unexpected.length) {
|
|
248
|
+
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported field generated.adapters[].${unexpected[0]}`);
|
|
249
|
+
}
|
|
250
|
+
for (const field of allowed) {
|
|
164
251
|
if (adapter[field] === undefined) {
|
|
165
252
|
return failure("invalid", "invalid-lockfile", `Missing adapter field: ${field}`);
|
|
166
253
|
}
|
|
167
254
|
}
|
|
168
|
-
if (adapter.adapter
|
|
169
|
-
return failure("unsupported", "unsupported-lockfile-shape", "
|
|
255
|
+
if (adapter.adapter === "opencode") {
|
|
256
|
+
return failure("unsupported", "unsupported-lockfile-shape", "opencode lockfile entries must use installed_roots.");
|
|
257
|
+
}
|
|
258
|
+
if (schemaVersion === 1 && adapter.adapter !== "codex") {
|
|
259
|
+
return failure("unsupported", "unsupported-lockfile-shape", "schema_version 1 supports only Codex lockfile entries.");
|
|
260
|
+
}
|
|
261
|
+
if (adapter.installed_root !== SINGLE_ROOTS[adapter.adapter]) {
|
|
262
|
+
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported installed root.");
|
|
263
|
+
}
|
|
264
|
+
if (!isSha256(adapter.tree_sha256)) {
|
|
265
|
+
return failure("invalid", "invalid-lockfile", "Adapter tree hash must be a SHA-256 value.");
|
|
266
|
+
}
|
|
267
|
+
if (!isNonNegativeInteger(adapter.file_count)) {
|
|
268
|
+
return failure("invalid", "invalid-lockfile", "Adapter file_count must be a non-negative integer.");
|
|
269
|
+
}
|
|
270
|
+
adapter.file_count = Number.parseInt(adapter.file_count, 10);
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function validateMultiRootAdapter(adapter) {
|
|
275
|
+
const allowed = [
|
|
276
|
+
"adapter",
|
|
277
|
+
"release",
|
|
278
|
+
"source",
|
|
279
|
+
"archive",
|
|
280
|
+
"archive_sha256",
|
|
281
|
+
"tree_hash_algorithm",
|
|
282
|
+
"installed_roots",
|
|
283
|
+
"root_hashes",
|
|
284
|
+
];
|
|
285
|
+
const unexpected = unexpectedFields(adapter, allowed);
|
|
286
|
+
if (unexpected.length) {
|
|
287
|
+
return failure("unsupported", "unsupported-lockfile-shape", `Unsupported field generated.adapters[].${unexpected[0]}`);
|
|
288
|
+
}
|
|
289
|
+
for (const field of allowed) {
|
|
290
|
+
if (adapter[field] === undefined) {
|
|
291
|
+
return failure("invalid", "invalid-lockfile", `Missing adapter field: ${field}`);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (adapter.adapter !== "opencode") {
|
|
295
|
+
return failure("unsupported", "unsupported-lockfile-shape", "Only opencode supports multi-root lockfile entries.");
|
|
296
|
+
}
|
|
297
|
+
const rootRoles = Object.keys(adapter.installed_roots).sort();
|
|
298
|
+
const hashRoles = Object.keys(adapter.root_hashes).sort();
|
|
299
|
+
if (!rootRoles.length || rootRoles.join("\n") !== hashRoles.join("\n")) {
|
|
300
|
+
return failure("invalid", "invalid-lockfile", "installed_roots and root_hashes roles must match.");
|
|
301
|
+
}
|
|
302
|
+
for (const role of rootRoles) {
|
|
303
|
+
if (!Object.hasOwn(OPENCODE_ROOTS, role) || adapter.installed_roots[role] !== OPENCODE_ROOTS[role]) {
|
|
304
|
+
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported opencode installed root.");
|
|
305
|
+
}
|
|
306
|
+
const hash = adapter.root_hashes[role];
|
|
307
|
+
if (!hash || !isSha256(hash.tree_sha256)) {
|
|
308
|
+
return failure("invalid", "invalid-lockfile", "Adapter root hash must be a SHA-256 value.");
|
|
309
|
+
}
|
|
310
|
+
if (!isNonNegativeInteger(hash.file_count)) {
|
|
311
|
+
return failure("invalid", "invalid-lockfile", "Adapter root file_count must be a non-negative integer.");
|
|
312
|
+
}
|
|
313
|
+
hash.file_count = Number.parseInt(hash.file_count, 10);
|
|
314
|
+
}
|
|
315
|
+
return undefined;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function validateAdapter(adapter, schemaVersion) {
|
|
319
|
+
if (!SUPPORTED_ADAPTERS.has(adapter.adapter)) {
|
|
320
|
+
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported lockfile adapter.");
|
|
170
321
|
}
|
|
171
322
|
if (!SUPPORTED_SOURCES.has(adapter.source)) {
|
|
172
323
|
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported lockfile adapter source.");
|
|
@@ -174,18 +325,16 @@ function validateAdapter(adapter) {
|
|
|
174
325
|
if (adapter.tree_hash_algorithm !== "rigorloop-tree-hash-v1") {
|
|
175
326
|
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported tree hash algorithm.");
|
|
176
327
|
}
|
|
177
|
-
if (adapter.
|
|
178
|
-
return failure("
|
|
328
|
+
if (!isSha256(adapter.archive_sha256)) {
|
|
329
|
+
return failure("invalid", "invalid-lockfile", "Adapter archive hash must be a SHA-256 value.");
|
|
179
330
|
}
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return failure("invalid", "invalid-lockfile", "Adapter file_count must be a non-negative integer.");
|
|
331
|
+
if (adapter.installed_roots !== undefined || adapter.root_hashes !== undefined) {
|
|
332
|
+
if (schemaVersion !== 2) {
|
|
333
|
+
return failure("unsupported", "unsupported-lockfile-shape", "Multi-root lockfile entries require schema_version 2.");
|
|
334
|
+
}
|
|
335
|
+
return validateMultiRootAdapter(adapter);
|
|
186
336
|
}
|
|
187
|
-
adapter
|
|
188
|
-
return undefined;
|
|
337
|
+
return validateSingleRootAdapter(adapter, schemaVersion);
|
|
189
338
|
}
|
|
190
339
|
|
|
191
340
|
export function parseLockfile(text) {
|
|
@@ -193,7 +342,7 @@ export function parseLockfile(text) {
|
|
|
193
342
|
return failure("invalid", "invalid-lockfile", "rigorloop.lock is empty or not text.");
|
|
194
343
|
}
|
|
195
344
|
if (/[\[\]{}]/.test(text)) {
|
|
196
|
-
return failure("invalid", "invalid-lockfile", "rigorloop.lock is not valid strict
|
|
345
|
+
return failure("invalid", "invalid-lockfile", "rigorloop.lock is not valid strict YAML.");
|
|
197
346
|
}
|
|
198
347
|
|
|
199
348
|
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
@@ -209,7 +358,8 @@ export function parseLockfile(text) {
|
|
|
209
358
|
}
|
|
210
359
|
}
|
|
211
360
|
const schemaVersion = parseScalar(top.get("schema_version"));
|
|
212
|
-
|
|
361
|
+
const parsedSchemaVersion = Number.parseInt(schemaVersion, 10);
|
|
362
|
+
if (!/^\d+$/.test(schemaVersion) || ![1, 2].includes(parsedSchemaVersion)) {
|
|
213
363
|
return failure("unsupported", "unsupported-lockfile-shape", "Unsupported lockfile schema_version.");
|
|
214
364
|
}
|
|
215
365
|
|
|
@@ -243,7 +393,7 @@ export function parseLockfile(text) {
|
|
|
243
393
|
return failure("invalid", "invalid-lockfile", "generated.adapters must contain at least one adapter entry.");
|
|
244
394
|
}
|
|
245
395
|
for (const adapter of adapterResult.adapters) {
|
|
246
|
-
const adapterError = validateAdapter(adapter);
|
|
396
|
+
const adapterError = validateAdapter(adapter, parsedSchemaVersion);
|
|
247
397
|
if (adapterError) {
|
|
248
398
|
return adapterError;
|
|
249
399
|
}
|
|
@@ -252,7 +402,7 @@ export function parseLockfile(text) {
|
|
|
252
402
|
return {
|
|
253
403
|
ok: true,
|
|
254
404
|
lockfile: {
|
|
255
|
-
schema_version:
|
|
405
|
+
schema_version: parsedSchemaVersion,
|
|
256
406
|
rigorloop: rigorloop.fields,
|
|
257
407
|
manifest: manifest.fields,
|
|
258
408
|
generated: {
|
|
@@ -265,7 +415,7 @@ export function parseLockfile(text) {
|
|
|
265
415
|
export function serializeLockfile(lockfile) {
|
|
266
416
|
const adapters = [...lockfile.generated.adapters].sort((left, right) => left.adapter.localeCompare(right.adapter));
|
|
267
417
|
const lines = [
|
|
268
|
-
|
|
418
|
+
`schema_version: ${lockfile.schema_version ?? 2}`,
|
|
269
419
|
"",
|
|
270
420
|
"rigorloop:",
|
|
271
421
|
` package: "${lockfile.rigorloop.package}"`,
|
|
@@ -285,11 +435,28 @@ export function serializeLockfile(lockfile) {
|
|
|
285
435
|
` source: ${adapter.source}`,
|
|
286
436
|
` archive: "${adapter.archive}"`,
|
|
287
437
|
` archive_sha256: "${adapter.archive_sha256}"`,
|
|
288
|
-
` installed_root: "${adapter.installed_root}"`,
|
|
289
|
-
` tree_hash_algorithm: ${adapter.tree_hash_algorithm}`,
|
|
290
|
-
` tree_sha256: "${adapter.tree_sha256}"`,
|
|
291
|
-
` file_count: ${adapter.file_count}`,
|
|
292
438
|
);
|
|
439
|
+
if (adapter.installed_roots) {
|
|
440
|
+
lines.push(` tree_hash_algorithm: ${adapter.tree_hash_algorithm}`, " installed_roots:");
|
|
441
|
+
for (const [role, root] of Object.entries(adapter.installed_roots)) {
|
|
442
|
+
lines.push(` ${role}: "${root}"`);
|
|
443
|
+
}
|
|
444
|
+
lines.push(" root_hashes:");
|
|
445
|
+
for (const [role, hash] of Object.entries(adapter.root_hashes)) {
|
|
446
|
+
lines.push(
|
|
447
|
+
` ${role}:`,
|
|
448
|
+
` tree_sha256: "${hash.tree_sha256}"`,
|
|
449
|
+
` file_count: ${hash.file_count}`,
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
lines.push(
|
|
454
|
+
` installed_root: "${adapter.installed_root}"`,
|
|
455
|
+
` tree_hash_algorithm: ${adapter.tree_hash_algorithm}`,
|
|
456
|
+
` tree_sha256: "${adapter.tree_sha256}"`,
|
|
457
|
+
` file_count: ${adapter.file_count}`,
|
|
458
|
+
);
|
|
459
|
+
}
|
|
293
460
|
}
|
|
294
461
|
return `${lines.join("\n")}\n`;
|
|
295
462
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"release": {
|
|
4
|
+
"version": "v0.2.0",
|
|
5
|
+
"source_repository": "xiongxianfei/rigorloop",
|
|
6
|
+
"source_commit": "0649434a75561bb8e2922a612e0121a095233687",
|
|
7
|
+
"release_tag": "v0.2.0",
|
|
8
|
+
"published_at": "2026-05-23"
|
|
9
|
+
},
|
|
10
|
+
"metadata": {
|
|
11
|
+
"url": "https://github.com/xiongxianfei/rigorloop/releases/download/v0.2.0/adapter-artifacts-v0.2.0.json",
|
|
12
|
+
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
|
13
|
+
},
|
|
14
|
+
"artifacts": [
|
|
15
|
+
{
|
|
16
|
+
"adapter": "codex",
|
|
17
|
+
"archive": "rigorloop-adapter-codex-v0.2.0.zip",
|
|
18
|
+
"url": "https://github.com/xiongxianfei/rigorloop/releases/download/v0.2.0/rigorloop-adapter-codex-v0.2.0.zip",
|
|
19
|
+
"sha256": "b7a8b5fcb4abf25eccb90868eb43d87943ee0bb526451910fb2d59f4844d41b3",
|
|
20
|
+
"size_bytes": 105317,
|
|
21
|
+
"install_root": ".agents/skills",
|
|
22
|
+
"tree_hash_algorithm": "rigorloop-tree-hash-v1",
|
|
23
|
+
"tree_sha256": "698be6488b06534ed927278f7d0671fd9ee7ead8f4e20d1df838894b45d139bf"
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
"validation": {
|
|
27
|
+
"command": "python scripts/validate-adapters.py --root <release-output-dir> --version v0.2.0",
|
|
28
|
+
"result": "pass"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"releases": {
|
|
4
|
-
"v0.
|
|
4
|
+
"v0.2.0": {
|
|
5
5
|
"source_repository": "xiongxianfei/rigorloop",
|
|
6
|
-
"release_tag": "v0.
|
|
7
|
-
"bundled_metadata": "adapter-artifacts-v0.
|
|
8
|
-
"bundled_metadata_sha256": "
|
|
6
|
+
"release_tag": "v0.2.0",
|
|
7
|
+
"bundled_metadata": "adapter-artifacts-v0.2.0.json",
|
|
8
|
+
"bundled_metadata_sha256": "686e41154de342f2852dd4745a5378d1440bc02a39255630cc009cc28f39fa06"
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
}
|