@open-agent-toolkit/cli 0.2.30 → 0.2.32
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/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +41 -0
- package/assets/docs/contributing/code.md +19 -7
- package/assets/docs/contributing/explainer-kit-verification.md +9 -1
- package/assets/docs/contributing/skills.md +9 -0
- package/assets/docs/provider-sync/commands.md +15 -10
- package/assets/docs/provider-sync/manifest-and-drift.md +23 -0
- package/assets/docs/provider-sync/providers.md +8 -2
- package/assets/docs/provider-sync/scope-and-surface.md +3 -1
- package/assets/docs/reference/file-locations.md +5 -0
- package/assets/docs/reference/troubleshooting.md +18 -0
- package/assets/docs/workflows/skills/explainer-kit-providers.md +16 -5
- package/assets/docs/workflows/skills/explainer-kit.md +98 -38
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +34 -22
- package/assets/skills/explainer-kit/SKILL.md +33 -8
- package/assets/skills/explainer-kit/briefs/project-recap.md +25 -7
- package/assets/skills/explainer-kit/recipes/project-recap.v2.json +72 -0
- package/assets/skills/explainer-kit/references/contracts.md +49 -17
- package/assets/skills/explainer-kit/references/destination-contract.md +141 -25
- package/assets/skills/explainer-kit/references/extension-contract.md +19 -10
- package/assets/skills/explainer-kit/references/visual-authoring.md +24 -0
- package/assets/skills/explainer-kit/references/visual-review.md +19 -5
- package/assets/skills/explainer-kit/schemas/author-request.v3.schema.json +241 -0
- package/assets/skills/explainer-kit/schemas/publish-receipt.v2.schema.json +215 -0
- package/assets/skills/explainer-kit/schemas/publish-request.v2.schema.json +34 -0
- package/assets/skills/explainer-kit/schemas/run-request.schema.json +4 -1
- package/assets/skills/explainer-kit/schemas/terminal-evidence.v1.schema.json +81 -0
- package/assets/skills/explainer-kit/schemas/visual-review-evidence.v1.schema.json +66 -0
- package/assets/skills/explainer-kit/scripts/lib/catalog.mjs +109 -3
- package/assets/skills/explainer-kit/scripts/lib/contracts.mjs +550 -17
- package/assets/skills/explainer-kit/scripts/lib/durability.mjs +90 -8
- package/assets/skills/explainer-kit/scripts/lib/fs-safe.mjs +5 -0
- package/assets/skills/explainer-kit/scripts/lib/internal-references.mjs +538 -0
- package/assets/skills/explainer-kit/scripts/lib/package-coverage.mjs +129 -11
- package/assets/skills/explainer-kit/scripts/lib/publication-policy.mjs +54 -0
- package/assets/skills/explainer-kit/scripts/lib/recipes.mjs +2 -1
- package/assets/skills/explainer-kit/scripts/lib/records.mjs +139 -22
- package/assets/skills/explainer-kit/scripts/lib/s3-roots.mjs +353 -0
- package/assets/skills/explainer-kit/scripts/lib/s3-static.mjs +237 -107
- package/assets/skills/explainer-kit/scripts/lib/set-plan.mjs +1 -0
- package/assets/skills/explainer-kit/scripts/lib/terminal-evidence.mjs +157 -0
- package/assets/skills/explainer-kit/scripts/lib/visual-review.mjs +26 -6
- package/assets/skills/explainer-kit/scripts/run.mjs +1006 -144
- package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +14 -2
- package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +14 -2
- package/assets/skills/oat-explainer-kit/SKILL.md +16 -3
- package/assets/skills/oat-explainer-kit/references/config-contract.md +13 -8
- package/assets/skills/oat-explainer-kit/references/lifecycle-contract.md +50 -6
- package/assets/skills/oat-explainer-kit/references/migration.md +2 -1
- package/assets/skills/oat-explainer-kit/references/visual-review-callback.md +11 -0
- package/assets/skills/oat-explainer-kit/scripts/bind-project-sources.mjs +37 -15
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +83 -0
- package/assets/skills/oat-explainer-kit/scripts/derive-destination.mjs +91 -0
- package/assets/skills/oat-explainer-kit/scripts/finalize-tracked-run.mjs +66 -10
- package/assets/skills/oat-explainer-kit/scripts/resolve-config.mjs +60 -21
- package/assets/skills/oat-explainer-kit/scripts/resolve-paths.mjs +52 -8
- package/assets/skills/oat-explainer-kit/scripts/run.mjs +271 -36
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
- package/assets/skills/oat-project-complete/SKILL.md +19 -3
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +8 -0
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +18 -0
- package/dist/commands/init/index.d.ts +2 -2
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +22 -13
- package/dist/commands/project/archive/archive-utils.d.ts.map +1 -1
- package/dist/commands/project/archive/archive-utils.js +57 -7
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts +29 -0
- package/dist/commands/project/archive/explainer-terminal-evidence.d.ts.map +1 -0
- package/dist/commands/project/archive/explainer-terminal-evidence.js +37 -0
- package/dist/commands/remove/skill/remove-skill.d.ts +4 -1
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +44 -5
- package/dist/commands/shared/adopt-stray.d.ts +5 -0
- package/dist/commands/shared/adopt-stray.d.ts.map +1 -1
- package/dist/commands/shared/adopt-stray.js +25 -4
- package/dist/commands/shared/native-skill-disposition.d.ts +22 -0
- package/dist/commands/shared/native-skill-disposition.d.ts.map +1 -0
- package/dist/commands/shared/native-skill-disposition.js +60 -0
- package/dist/commands/status/index.d.ts +2 -2
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +22 -13
- package/dist/config/oat-config.d.ts +2 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +4 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +1 -0
- package/dist/engine/compute-plan.d.ts +3 -2
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/providers/copilot/paths.d.ts.map +1 -1
- package/dist/providers/copilot/paths.js +6 -4
- package/package.json +2 -2
- package/dist/commands/shared/cursor-skill-disposition.d.ts +0 -17
- package/dist/commands/shared/cursor-skill-disposition.d.ts.map +0 -1
- package/dist/commands/shared/cursor-skill-disposition.js +0 -41
- /package/assets/skills/explainer-kit/recipes/{project-recap.json → project-recap.v1.json} +0 -0
- /package/assets/skills/explainer-kit/schemas/{publish-receipt.schema.json → publish-receipt.v1.schema.json} +0 -0
- /package/assets/skills/explainer-kit/schemas/{publish-request.schema.json → publish-request.v1.schema.json} +0 -0
|
@@ -15,6 +15,7 @@ export const EXPLAINER_CONFIG_KEYS = Object.freeze([
|
|
|
15
15
|
'explainers.publish.s3Uri',
|
|
16
16
|
'explainers.publish.publicBaseUrl',
|
|
17
17
|
'explainers.publish.awsRegion',
|
|
18
|
+
'explainers.publish.publicAccess',
|
|
18
19
|
'explainers.publish.awsProfile',
|
|
19
20
|
'workflow.explainers.projectExplainer',
|
|
20
21
|
'workflow.explainers.projectRecap',
|
|
@@ -115,7 +116,7 @@ export async function resolveExplainerConfig({
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
const publish = resolvePublish(values);
|
|
119
|
+
const { publish, publishReport } = resolvePublish(values, sources);
|
|
119
120
|
const preferences = {
|
|
120
121
|
projectExplainer: resolvePreference(
|
|
121
122
|
'workflow.explainers.projectExplainer',
|
|
@@ -127,7 +128,15 @@ export async function resolveExplainerConfig({
|
|
|
127
128
|
),
|
|
128
129
|
};
|
|
129
130
|
|
|
130
|
-
return {
|
|
131
|
+
return {
|
|
132
|
+
values,
|
|
133
|
+
sources,
|
|
134
|
+
theme,
|
|
135
|
+
publish,
|
|
136
|
+
publishReport,
|
|
137
|
+
preferences,
|
|
138
|
+
warnings,
|
|
139
|
+
};
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
export function toExplainerRunRequest({
|
|
@@ -170,8 +179,9 @@ export function toExplainerRunRequest({
|
|
|
170
179
|
);
|
|
171
180
|
}
|
|
172
181
|
durability.publish = {
|
|
173
|
-
schemaVersion: 'explainer-kit.publish-request/
|
|
182
|
+
schemaVersion: 'explainer-kit.publish-request/v2',
|
|
174
183
|
...resolvedConfig.publish,
|
|
184
|
+
publicAccess: resolvedConfig.publish.publicAccess ?? 'public',
|
|
175
185
|
siteRoot: join(outputRoot, slug, 'site'),
|
|
176
186
|
manifestPath: join(outputRoot, slug, 'manifest.json'),
|
|
177
187
|
};
|
|
@@ -179,7 +189,10 @@ export function toExplainerRunRequest({
|
|
|
179
189
|
|
|
180
190
|
return {
|
|
181
191
|
schemaVersion: 'explainer-kit.run-request/v1',
|
|
182
|
-
recipe: {
|
|
192
|
+
recipe: {
|
|
193
|
+
id: recipe,
|
|
194
|
+
version: recipe === 'project-recap' ? '2' : '1',
|
|
195
|
+
},
|
|
183
196
|
slug,
|
|
184
197
|
outputRoot,
|
|
185
198
|
factBase,
|
|
@@ -254,6 +267,12 @@ function normalizeRuntimeValue(key, value) {
|
|
|
254
267
|
if (key === 'explainers.publish.provider' && normalized !== 's3-static') {
|
|
255
268
|
throw new Error(`${key} runtime override must be s3-static.`);
|
|
256
269
|
}
|
|
270
|
+
if (
|
|
271
|
+
key === 'explainers.publish.publicAccess' &&
|
|
272
|
+
!['public', 'protected'].includes(normalized)
|
|
273
|
+
) {
|
|
274
|
+
throw new Error(`${key} runtime override must be public or protected.`);
|
|
275
|
+
}
|
|
257
276
|
if (key === 'explainers.defaults.style' && !STYLES.has(normalized)) {
|
|
258
277
|
throw new Error(
|
|
259
278
|
`${key} runtime override must name a curated explainer style.`,
|
|
@@ -283,27 +302,30 @@ function normalizeRuntimeValue(key, value) {
|
|
|
283
302
|
return normalized;
|
|
284
303
|
}
|
|
285
304
|
|
|
286
|
-
function resolvePublish(values) {
|
|
287
|
-
const provider = nullableString(values['explainers.publish.provider']);
|
|
288
|
-
if (!provider) {
|
|
289
|
-
return null;
|
|
290
|
-
}
|
|
291
|
-
if (provider !== 's3-static') {
|
|
292
|
-
throw new Error(`Unsupported explainer publish provider: ${provider}`);
|
|
293
|
-
}
|
|
294
|
-
|
|
305
|
+
function resolvePublish(values, sources) {
|
|
295
306
|
const fields = {
|
|
307
|
+
provider: nullableString(values['explainers.publish.provider']),
|
|
296
308
|
s3Uri: nullableString(values['explainers.publish.s3Uri']),
|
|
297
309
|
publicBaseUrl: nullableString(values['explainers.publish.publicBaseUrl']),
|
|
298
310
|
awsRegion: nullableString(values['explainers.publish.awsRegion']),
|
|
299
311
|
};
|
|
312
|
+
if (fields.provider && fields.provider !== 's3-static') {
|
|
313
|
+
throw new Error(
|
|
314
|
+
`Unsupported explainer publish provider: ${fields.provider}`,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
300
317
|
const missing = Object.entries(fields)
|
|
301
318
|
.filter(([, value]) => !value)
|
|
302
319
|
.map(([key]) => key);
|
|
303
320
|
if (missing.length > 0) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
321
|
+
return {
|
|
322
|
+
publish: null,
|
|
323
|
+
publishReport: {
|
|
324
|
+
mode: 'build-only',
|
|
325
|
+
publishCapable: false,
|
|
326
|
+
missing,
|
|
327
|
+
},
|
|
328
|
+
};
|
|
307
329
|
}
|
|
308
330
|
if (!/^s3:\/\/[^/\s]+(?:\/.*)?$/.test(fields.s3Uri)) {
|
|
309
331
|
throw new Error('explainers.publish.s3Uri must be a valid s3:// URI.');
|
|
@@ -315,12 +337,29 @@ function resolvePublish(values) {
|
|
|
315
337
|
}
|
|
316
338
|
|
|
317
339
|
const awsProfile = nullableString(values['explainers.publish.awsProfile']);
|
|
340
|
+
const publicAccess =
|
|
341
|
+
nullableString(values['explainers.publish.publicAccess']) ?? 'public';
|
|
342
|
+
if (!['public', 'protected'].includes(publicAccess)) {
|
|
343
|
+
throw new Error(
|
|
344
|
+
'explainers.publish.publicAccess must be public or protected.',
|
|
345
|
+
);
|
|
346
|
+
}
|
|
318
347
|
return {
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
348
|
+
publish: {
|
|
349
|
+
provider: fields.provider,
|
|
350
|
+
s3Uri: fields.s3Uri.replace(/\/+$/, ''),
|
|
351
|
+
publicBaseUrl: fields.publicBaseUrl.replace(/\/+$/, ''),
|
|
352
|
+
awsRegion: fields.awsRegion,
|
|
353
|
+
...(sources['explainers.publish.publicAccess'] !== 'default'
|
|
354
|
+
? { publicAccess }
|
|
355
|
+
: {}),
|
|
356
|
+
...(awsProfile ? { awsProfile } : {}),
|
|
357
|
+
},
|
|
358
|
+
publishReport: {
|
|
359
|
+
mode: 'publish-capable',
|
|
360
|
+
publishCapable: true,
|
|
361
|
+
missing: [],
|
|
362
|
+
},
|
|
324
363
|
};
|
|
325
364
|
}
|
|
326
365
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { lstat, realpath } from 'node:fs/promises';
|
|
2
|
-
import { isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
2
|
+
import { basename, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
3
3
|
|
|
4
4
|
export async function resolveExplainerOutputRoot({
|
|
5
5
|
repoRoot,
|
|
6
6
|
invocation,
|
|
7
7
|
activeProject,
|
|
8
8
|
outputRoot,
|
|
9
|
+
slug,
|
|
9
10
|
}) {
|
|
10
11
|
if (!repoRoot) {
|
|
11
12
|
throw new TypeError('repoRoot is required.');
|
|
@@ -17,19 +18,26 @@ export async function resolveExplainerOutputRoot({
|
|
|
17
18
|
'Direct callers must provide an explicit outputRoot to the core.',
|
|
18
19
|
);
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
+
const resolvedRoot = await resolveSafePath(outputRoot, {
|
|
21
22
|
baseRoot: repoRoot,
|
|
22
23
|
field: 'outputRoot',
|
|
23
24
|
});
|
|
25
|
+
assertParentOutputRoot(resolvedRoot, slug);
|
|
26
|
+
return resolvedRoot;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
const canonicalRepoRoot = await realpath(resolve(repoRoot));
|
|
27
30
|
if (invocation === 'repo') {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const resolvedRoot = await resolveSafePath(
|
|
32
|
+
'.oat/repo/reference/explainers',
|
|
33
|
+
{
|
|
34
|
+
baseRoot: canonicalRepoRoot,
|
|
35
|
+
confinedRoot: canonicalRepoRoot,
|
|
36
|
+
field: 'repo explainer output root',
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
assertParentOutputRoot(resolvedRoot, slug);
|
|
40
|
+
return resolvedRoot;
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
if (invocation !== 'project') {
|
|
@@ -49,11 +57,13 @@ export async function resolveExplainerOutputRoot({
|
|
|
49
57
|
throw new Error('The active project cannot be the repository root.');
|
|
50
58
|
}
|
|
51
59
|
|
|
52
|
-
|
|
60
|
+
const resolvedRoot = await resolveSafePath(join(projectRoot, 'explainers'), {
|
|
53
61
|
baseRoot: canonicalRepoRoot,
|
|
54
62
|
confinedRoot: projectRoot,
|
|
55
63
|
field: 'project explainer output root',
|
|
56
64
|
});
|
|
65
|
+
assertParentOutputRoot(resolvedRoot, slug);
|
|
66
|
+
return resolvedRoot;
|
|
57
67
|
}
|
|
58
68
|
|
|
59
69
|
export async function resolveSourceAwarePath({
|
|
@@ -164,3 +174,37 @@ function isWithin(root, target) {
|
|
|
164
174
|
function isMissing(error) {
|
|
165
175
|
return error && typeof error === 'object' && error.code === 'ENOENT';
|
|
166
176
|
}
|
|
177
|
+
|
|
178
|
+
function assertParentOutputRoot(outputRoot, slug) {
|
|
179
|
+
if (slug === undefined) return;
|
|
180
|
+
const normalizedSlug = normalizeRunSlug(slug);
|
|
181
|
+
if (basename(outputRoot) === normalizedSlug) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Output root already ends in run slug "${normalizedSlug}"; supply the parent output root to avoid double-nesting.`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function normalizeRunSlug(candidate) {
|
|
189
|
+
if (
|
|
190
|
+
typeof candidate !== 'string' ||
|
|
191
|
+
candidate.includes('/') ||
|
|
192
|
+
candidate.includes('\\') ||
|
|
193
|
+
candidate.includes('\0') ||
|
|
194
|
+
candidate === '.' ||
|
|
195
|
+
candidate === '..'
|
|
196
|
+
) {
|
|
197
|
+
throw new Error('Run slug must be text, not a path or traversal value.');
|
|
198
|
+
}
|
|
199
|
+
const slug = candidate
|
|
200
|
+
.normalize('NFKD')
|
|
201
|
+
.replaceAll(/\p{Mark}/gu, '')
|
|
202
|
+
.toLowerCase()
|
|
203
|
+
.trim()
|
|
204
|
+
.replaceAll(/[^a-z0-9]+/g, '-')
|
|
205
|
+
.replaceAll(/^-+|-+$/g, '');
|
|
206
|
+
if (!slug) {
|
|
207
|
+
throw new Error('Run slug must contain at least one letter or number.');
|
|
208
|
+
}
|
|
209
|
+
return slug;
|
|
210
|
+
}
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import { dirname, join, resolve } from 'node:path';
|
|
4
|
+
import { basename, dirname, join, resolve } from 'node:path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
bindProjectSources,
|
|
9
|
+
bindRepositorySources,
|
|
10
|
+
} from './bind-project-sources.mjs';
|
|
8
11
|
import { checkCoreCompatibility } from './check-core.mjs';
|
|
12
|
+
import { deriveExplainerDestination } from './derive-destination.mjs';
|
|
9
13
|
import {
|
|
10
14
|
resolveExplainerConfig,
|
|
11
15
|
toExplainerRunRequest,
|
|
12
16
|
} from './resolve-config.mjs';
|
|
13
17
|
import { resolveExplainerOutputRoot } from './resolve-paths.mjs';
|
|
14
18
|
|
|
15
|
-
export const MINIMUM_CORE_VERSION = '2.0
|
|
19
|
+
export const MINIMUM_CORE_VERSION = '2.1.0';
|
|
16
20
|
const ADAPTER_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
17
21
|
|
|
18
22
|
export async function runOatExplainer({
|
|
@@ -80,21 +84,52 @@ export async function runOatExplainer({
|
|
|
80
84
|
repoRoot,
|
|
81
85
|
invocation,
|
|
82
86
|
activeProject,
|
|
87
|
+
slug,
|
|
83
88
|
});
|
|
84
|
-
|
|
89
|
+
const destination = resolvedConfig.publish
|
|
90
|
+
? deriveExplainerDestination({
|
|
91
|
+
invocation,
|
|
92
|
+
...(invocation === 'project' && {
|
|
93
|
+
projectSlug: basename(activeProject),
|
|
94
|
+
}),
|
|
95
|
+
s3Uri: resolvedConfig.publish.s3Uri,
|
|
96
|
+
publicBaseUrl: resolvedConfig.publish.publicBaseUrl,
|
|
97
|
+
})
|
|
98
|
+
: null;
|
|
99
|
+
let bound;
|
|
100
|
+
if (invocation === 'project') {
|
|
101
|
+
if (!activeProject) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
'Project artifact binding requires an activeProject input.',
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
bound = await bindProjectSources({
|
|
107
|
+
projectRoot: resolve(repoRoot, activeProject),
|
|
108
|
+
repoRoot,
|
|
109
|
+
recipe,
|
|
110
|
+
suppliedFactBasePath,
|
|
111
|
+
});
|
|
112
|
+
} else if (invocation === 'repo') {
|
|
113
|
+
bound = await bindRepositorySources({
|
|
114
|
+
repoRoot,
|
|
115
|
+
suppliedFactBasePath,
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
85
118
|
throw new Error(
|
|
86
|
-
'
|
|
119
|
+
'The OAT adapter accepts project or repository invocations; direct callers invoke the core with an explicit output root.',
|
|
87
120
|
);
|
|
88
121
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
122
|
+
const requestConfig = destination
|
|
123
|
+
? {
|
|
124
|
+
...resolvedConfig,
|
|
125
|
+
publish: {
|
|
126
|
+
...resolvedConfig.publish,
|
|
127
|
+
...destination,
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
: resolvedConfig;
|
|
96
131
|
const request = toExplainerRunRequest({
|
|
97
|
-
resolvedConfig,
|
|
132
|
+
resolvedConfig: requestConfig,
|
|
98
133
|
recipe,
|
|
99
134
|
slug,
|
|
100
135
|
outputRoot,
|
|
@@ -181,13 +216,6 @@ export async function runOatExplainer({
|
|
|
181
216
|
}),
|
|
182
217
|
reviewedSource: bound.reviewedSource,
|
|
183
218
|
});
|
|
184
|
-
const criticContractError = result?.errors?.find(
|
|
185
|
-
({ message }) =>
|
|
186
|
-
typeof message === 'string' && message.includes('critic result contract'),
|
|
187
|
-
);
|
|
188
|
-
if (criticContractError) {
|
|
189
|
-
throw new Error(criticContractError.message);
|
|
190
|
-
}
|
|
191
219
|
const manifest = await readManifest(result, request);
|
|
192
220
|
return {
|
|
193
221
|
compatibility,
|
|
@@ -195,7 +223,9 @@ export async function runOatExplainer({
|
|
|
195
223
|
manifest,
|
|
196
224
|
result,
|
|
197
225
|
marking: result.marking ?? null,
|
|
226
|
+
publication: result.publication ?? null,
|
|
198
227
|
outputRoot,
|
|
228
|
+
destination,
|
|
199
229
|
};
|
|
200
230
|
}
|
|
201
231
|
|
|
@@ -204,10 +234,11 @@ export function supportsAdaptiveSetPlanning(version) {
|
|
|
204
234
|
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-|$)/);
|
|
205
235
|
if (!match) return false;
|
|
206
236
|
const [major, minor, patch] = match.slice(1).map(Number);
|
|
237
|
+
const [minimumMajor, minimumMinor, minimumPatch] =
|
|
238
|
+
MINIMUM_CORE_VERSION.split('.').map(Number);
|
|
207
239
|
return (
|
|
208
|
-
major ===
|
|
209
|
-
(minor >
|
|
210
|
-
(minor === 0 && patch >= Number(MINIMUM_CORE_VERSION.split('.')[2])))
|
|
240
|
+
major === minimumMajor &&
|
|
241
|
+
(minor > minimumMinor || (minor === minimumMinor && patch >= minimumPatch))
|
|
211
242
|
);
|
|
212
243
|
}
|
|
213
244
|
|
|
@@ -467,11 +498,8 @@ async function resolveLifecycleBrowserSession({
|
|
|
467
498
|
return core.assertBrowserProbeSession(resolvedSession, {
|
|
468
499
|
allowFixture: !required,
|
|
469
500
|
});
|
|
470
|
-
} catch
|
|
471
|
-
const error = new Error(
|
|
472
|
-
`Browser session validation failed: ${cause?.message ?? String(cause)}`,
|
|
473
|
-
{ cause },
|
|
474
|
-
);
|
|
501
|
+
} catch {
|
|
502
|
+
const error = new Error('Browser session validation failed.');
|
|
475
503
|
error.code = 'E_BROWSER_PROBE_REQUIRED';
|
|
476
504
|
throw error;
|
|
477
505
|
}
|
|
@@ -633,24 +661,29 @@ async function readManifest(result, request) {
|
|
|
633
661
|
return manifest;
|
|
634
662
|
}
|
|
635
663
|
|
|
636
|
-
async function
|
|
664
|
+
export async function runOatExplainerCli(
|
|
665
|
+
argv = process.argv.slice(2),
|
|
666
|
+
io = console,
|
|
667
|
+
run = runOatExplainer,
|
|
668
|
+
) {
|
|
637
669
|
try {
|
|
638
670
|
if (argv.length !== 2 || argv[0] !== '--context') {
|
|
639
671
|
throw new Error('Usage: run.mjs --context <adapter-context.json>');
|
|
640
672
|
}
|
|
641
673
|
const context = JSON.parse(await readFile(argv[1], 'utf8'));
|
|
642
|
-
const result = await
|
|
643
|
-
io.log(JSON.stringify(result, null, 2));
|
|
674
|
+
const result = await run(context);
|
|
675
|
+
io.log(JSON.stringify(projectAdapterCliResult(result), null, 2));
|
|
644
676
|
return result.result.outcome === 'failed' ? 1 : 0;
|
|
645
|
-
} catch
|
|
677
|
+
} catch {
|
|
646
678
|
io.error(
|
|
647
679
|
JSON.stringify(
|
|
648
680
|
{
|
|
649
681
|
outcome: 'failed',
|
|
650
|
-
|
|
682
|
+
reasons: [
|
|
651
683
|
{
|
|
652
|
-
|
|
653
|
-
|
|
684
|
+
stage: 'finalization',
|
|
685
|
+
kind: 'pipeline-failure',
|
|
686
|
+
count: 1,
|
|
654
687
|
},
|
|
655
688
|
],
|
|
656
689
|
},
|
|
@@ -662,9 +695,211 @@ async function runCli(argv = process.argv.slice(2), io = console) {
|
|
|
662
695
|
}
|
|
663
696
|
}
|
|
664
697
|
|
|
698
|
+
function projectAdapterCliResult(value) {
|
|
699
|
+
if (!isObject(value) || !isObject(value.result)) {
|
|
700
|
+
return {
|
|
701
|
+
result: {
|
|
702
|
+
outcome: 'failed',
|
|
703
|
+
reasons: [
|
|
704
|
+
{
|
|
705
|
+
stage: 'finalization',
|
|
706
|
+
kind: 'pipeline-failure',
|
|
707
|
+
count: 1,
|
|
708
|
+
},
|
|
709
|
+
],
|
|
710
|
+
},
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
const projected = {};
|
|
714
|
+
for (const key of ['compatibility', 'request', 'manifest', 'destination']) {
|
|
715
|
+
if (isObject(value[key])) projected[key] = structuredClone(value[key]);
|
|
716
|
+
}
|
|
717
|
+
for (const key of ['marking', 'outputRoot']) {
|
|
718
|
+
if (typeof value[key] === 'string' || value[key] === null) {
|
|
719
|
+
projected[key] = value[key];
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
projected.result = projectAdapterRunResult(value.result);
|
|
723
|
+
const publication = projectAdapterPublication(value.publication);
|
|
724
|
+
if (publication) projected.publication = publication;
|
|
725
|
+
return projected;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
function projectAdapterRunResult(value) {
|
|
729
|
+
const projected = {};
|
|
730
|
+
for (const key of [
|
|
731
|
+
'runId',
|
|
732
|
+
'runRoot',
|
|
733
|
+
'manifestPath',
|
|
734
|
+
'buildRecordPath',
|
|
735
|
+
'outcome',
|
|
736
|
+
'marking',
|
|
737
|
+
]) {
|
|
738
|
+
if (typeof value[key] === 'string') projected[key] = value[key];
|
|
739
|
+
}
|
|
740
|
+
if (Array.isArray(value.warnings)) {
|
|
741
|
+
projected.warnings = [
|
|
742
|
+
...new Set(value.warnings.filter(isAdapterWarningCode)),
|
|
743
|
+
];
|
|
744
|
+
}
|
|
745
|
+
for (const key of ['discovery', 'approval']) {
|
|
746
|
+
if (isObject(value[key])) projected[key] = structuredClone(value[key]);
|
|
747
|
+
}
|
|
748
|
+
const reasons = projectAdapterReasons(value.reasons);
|
|
749
|
+
if (reasons.length > 0) projected.reasons = reasons;
|
|
750
|
+
const visualReview = projectAdapterVisualReview(value.visualReview);
|
|
751
|
+
if (visualReview) projected.visualReview = visualReview;
|
|
752
|
+
const publication = projectAdapterPublication(value.publication);
|
|
753
|
+
if (publication) projected.publication = publication;
|
|
754
|
+
return projected;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
function projectAdapterVisualReview(value) {
|
|
758
|
+
if (!isObject(value)) return null;
|
|
759
|
+
const reasons = projectAdapterReasons(value.reasons);
|
|
760
|
+
if (
|
|
761
|
+
value.schemaVersion !== 'explainer-kit.visual-review-evidence/v1' ||
|
|
762
|
+
typeof value.requestHash !== 'string' ||
|
|
763
|
+
![1, 2].includes(value.attempt) ||
|
|
764
|
+
!['pass', 'correct', 'failed'].includes(value.disposition) ||
|
|
765
|
+
!Array.isArray(value.reasons) ||
|
|
766
|
+
reasons.length !== value.reasons.length
|
|
767
|
+
) {
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
return {
|
|
771
|
+
schemaVersion: value.schemaVersion,
|
|
772
|
+
requestHash: value.requestHash,
|
|
773
|
+
attempt: value.attempt,
|
|
774
|
+
disposition: value.disposition,
|
|
775
|
+
reasons,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
function projectAdapterPublication(value) {
|
|
780
|
+
if (!isObject(value)) return null;
|
|
781
|
+
if (
|
|
782
|
+
value.schemaVersion !== 'explainer-kit.publish-summary/v1' &&
|
|
783
|
+
value.schemaVersion !== 'explainer-kit.publish-summary/v2'
|
|
784
|
+
) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
return {
|
|
788
|
+
schemaVersion: value.schemaVersion,
|
|
789
|
+
...(typeof value.receiptSchemaVersion === 'string' && {
|
|
790
|
+
receiptSchemaVersion: value.receiptSchemaVersion,
|
|
791
|
+
}),
|
|
792
|
+
...(typeof value.publicAccess === 'string' && {
|
|
793
|
+
publicAccess: value.publicAccess,
|
|
794
|
+
}),
|
|
795
|
+
...(Array.isArray(value.artifacts) && {
|
|
796
|
+
artifacts: value.artifacts.map((artifact) =>
|
|
797
|
+
isObject(artifact)
|
|
798
|
+
? {
|
|
799
|
+
...pickAdapterStringFields(artifact, [
|
|
800
|
+
'relativePath',
|
|
801
|
+
'publicUrl',
|
|
802
|
+
's3Uri',
|
|
803
|
+
'hash',
|
|
804
|
+
'contentType',
|
|
805
|
+
]),
|
|
806
|
+
...(isObject(artifact.source) && {
|
|
807
|
+
source: pickAdapterStringFields(artifact.source, [
|
|
808
|
+
'kind',
|
|
809
|
+
'artifactId',
|
|
810
|
+
'name',
|
|
811
|
+
]),
|
|
812
|
+
}),
|
|
813
|
+
...(isObject(artifact.objectVerification) && {
|
|
814
|
+
objectVerification: projectAdapterVerification(
|
|
815
|
+
artifact.objectVerification,
|
|
816
|
+
),
|
|
817
|
+
}),
|
|
818
|
+
...(isObject(artifact.publicVerification) && {
|
|
819
|
+
publicVerification: projectAdapterVerification(
|
|
820
|
+
artifact.publicVerification,
|
|
821
|
+
),
|
|
822
|
+
}),
|
|
823
|
+
}
|
|
824
|
+
: {},
|
|
825
|
+
),
|
|
826
|
+
}),
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function projectAdapterVerification(value) {
|
|
831
|
+
return {
|
|
832
|
+
...pickAdapterStringFields(value, ['status', 'method', 'hash']),
|
|
833
|
+
...(Number.isInteger(value.httpStatus) && {
|
|
834
|
+
httpStatus: value.httpStatus,
|
|
835
|
+
}),
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function projectAdapterReasons(value) {
|
|
840
|
+
if (!Array.isArray(value)) return [];
|
|
841
|
+
return value.flatMap((reason) => {
|
|
842
|
+
if (
|
|
843
|
+
!isObject(reason) ||
|
|
844
|
+
![
|
|
845
|
+
'planning',
|
|
846
|
+
'authoring',
|
|
847
|
+
'rendering',
|
|
848
|
+
'link-validation',
|
|
849
|
+
'browser-review',
|
|
850
|
+
'visual-review',
|
|
851
|
+
'durability',
|
|
852
|
+
'finalization',
|
|
853
|
+
].includes(reason.stage) ||
|
|
854
|
+
![
|
|
855
|
+
'finding',
|
|
856
|
+
'provider-failure',
|
|
857
|
+
'pipeline-failure',
|
|
858
|
+
'superseded',
|
|
859
|
+
].includes(reason.kind) ||
|
|
860
|
+
!Number.isInteger(reason.count) ||
|
|
861
|
+
reason.count < 1 ||
|
|
862
|
+
reason.count > 50
|
|
863
|
+
) {
|
|
864
|
+
return [];
|
|
865
|
+
}
|
|
866
|
+
return [
|
|
867
|
+
{
|
|
868
|
+
stage: reason.stage,
|
|
869
|
+
kind: reason.kind,
|
|
870
|
+
...(typeof reason.artifactId === 'string' && {
|
|
871
|
+
artifactId: reason.artifactId,
|
|
872
|
+
}),
|
|
873
|
+
count: reason.count,
|
|
874
|
+
},
|
|
875
|
+
];
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function pickAdapterStringFields(value, keys) {
|
|
880
|
+
return Object.fromEntries(
|
|
881
|
+
keys.flatMap((key) =>
|
|
882
|
+
typeof value[key] === 'string' ? [[key, value[key]]] : [],
|
|
883
|
+
),
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function isAdapterWarningCode(value) {
|
|
888
|
+
return (
|
|
889
|
+
typeof value === 'string' &&
|
|
890
|
+
/^(?:fact-base-freshness-warning|theme-selection-normalized|durability-evidence-required|publish-receipt-evidence-required|(?:expansion|guideline|render|qa)-[a-z0-9-]+|visual-review-required:[a-z0-9-]+|stage-reopened:[a-z0-9-]+:[0-9TZ:.-]+|missing-(?:theme-token|required-anchor):[a-z0-9-]+)$/.test(
|
|
891
|
+
value,
|
|
892
|
+
)
|
|
893
|
+
);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
function isObject(value) {
|
|
897
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
898
|
+
}
|
|
899
|
+
|
|
665
900
|
if (
|
|
666
901
|
process.argv[1] &&
|
|
667
902
|
pathToFileURL(process.argv[1]).href === import.meta.url
|
|
668
903
|
) {
|
|
669
|
-
process.exitCode = await
|
|
904
|
+
process.exitCode = await runOatExplainerCli();
|
|
670
905
|
}
|
|
@@ -259,8 +259,8 @@ remains immutable baseline evidence for the original p01-t01 verification.
|
|
|
259
259
|
| `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG` |
|
|
260
260
|
| `oat-project-dispatch-subagents/SKILL.md` | `eca03ad1ca12 -> PDISPATCH-01`; `59fbcdc79cea -> PDISPATCH-01` |
|
|
261
261
|
| `oat-project-plan/SKILL.md` | `f99e44b39932 -> PLAN-12`; `7e6a9854504b -> NG` |
|
|
262
|
-
| `oat-project-implement/references/completion-and-closeout.md` | `6909a5a5a1fa -> IMPLEMENT-19`; `a7c02ef670fd -> IMPLEMENT-19`
|
|
263
|
-
| `oat-project-complete/SKILL.md` | `ffad9f909dba -> COMPLETE-01`; `ffe636f736e8 -> COMPLETE-01`; `9262624c148f -> COMPLETE-01`; `23ec8b6a5cee -> COMPLETE-01`; `9e6c4d7cc3a8 -> COMPLETE-01`; `47383d4ab654 -> COMPLETE-01`; `ba34449bd586 -> COMPLETE-01`; `
|
|
262
|
+
| `oat-project-implement/references/completion-and-closeout.md` | `6909a5a5a1fa -> IMPLEMENT-19`; `a7c02ef670fd -> IMPLEMENT-19`; `9dde56d89a71 -> IMPLEMENT-16`; `13c41b2b2590 -> IMPLEMENT-16` |
|
|
263
|
+
| `oat-project-complete/SKILL.md` | `ffad9f909dba -> COMPLETE-01`; `ffe636f736e8 -> COMPLETE-01`; `9262624c148f -> COMPLETE-01`; `23ec8b6a5cee -> COMPLETE-01`; `9e6c4d7cc3a8 -> COMPLETE-01`; `47383d4ab654 -> COMPLETE-01`; `ba34449bd586 -> COMPLETE-01`; `0177956707aa -> NG`; `8305b5bb65ef -> NG`; `eb3e75663ac0 -> NG` |
|
|
264
264
|
|
|
265
265
|
## Prompt-scan comparison
|
|
266
266
|
|