release-skill 0.9.10 → 0.9.11
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/.claude-plugin/plugin.json +1 -1
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.kimi-plugin/plugin.json +1 -1
- package/CHANGELOG.md +24 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +22 -12
- package/README.zh-CN.md +21 -12
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/consumer-contract-vectors.json +7 -7
- package/adapters/claude/bin/error-codes.json +1 -1
- package/adapters/claude/bin/foundation-resource-binding.json +1 -1
- package/adapters/claude/bin/registry.json +8 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +1018 -899
- package/adapters/claude/bin/rules.json +1 -1
- package/adapters/claude/data/hosts/codebuddy/host-descriptor.json +5 -0
- package/adapters/claude/schemas/release-project.schema.json +1 -1
- package/adapters/claude/src/schemas/engineering-baseline.schema.json +77 -0
- package/adapters/claude/src/schemas/host-descriptor.schema.json +9 -2
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/consumer-contract-vectors.json +7 -7
- package/adapters/codex/bin/error-codes.json +1 -1
- package/adapters/codex/bin/foundation-resource-binding.json +1 -1
- package/adapters/codex/bin/registry.json +8 -1
- package/adapters/codex/bin/release-skill.bundle.mjs +1018 -899
- package/adapters/codex/bin/rules.json +1 -1
- package/adapters/codex/data/hosts/codebuddy/host-descriptor.json +5 -0
- package/adapters/codex/schemas/release-project.schema.json +1 -1
- package/adapters/codex/src/schemas/engineering-baseline.schema.json +77 -0
- package/adapters/codex/src/schemas/host-descriptor.schema.json +9 -2
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/consumer-contract-vectors.json +7 -7
- package/adapters/kimi/bin/error-codes.json +1 -1
- package/adapters/kimi/bin/foundation-resource-binding.json +1 -1
- package/adapters/kimi/bin/registry.json +8 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +1018 -899
- package/adapters/kimi/bin/rules.json +1 -1
- package/adapters/kimi/data/hosts/codebuddy/host-descriptor.json +5 -0
- package/adapters/kimi/schemas/release-project.schema.json +1 -1
- package/adapters/kimi/src/schemas/engineering-baseline.schema.json +77 -0
- package/adapters/kimi/src/schemas/host-descriptor.schema.json +9 -2
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/consumer-contract-vectors.json +7 -7
- package/adapters/workbuddy/bin/error-codes.json +1 -1
- package/adapters/workbuddy/bin/foundation-resource-binding.json +1 -1
- package/adapters/workbuddy/bin/registry.json +8 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +1018 -899
- package/adapters/workbuddy/bin/rules.json +1 -1
- package/adapters/workbuddy/data/hosts/codebuddy/host-descriptor.json +5 -0
- package/adapters/workbuddy/schemas/release-project.schema.json +1 -1
- package/adapters/workbuddy/src/schemas/engineering-baseline.schema.json +77 -0
- package/adapters/workbuddy/src/schemas/host-descriptor.schema.json +9 -2
- package/bin/consumer-contract-vectors.json +7 -7
- package/bin/error-codes.json +1 -1
- package/bin/foundation-resource-binding.json +1 -1
- package/bin/registry.json +8 -1
- package/bin/release-skill.bundle.mjs +1018 -899
- package/bin/rules.json +1 -1
- package/data/hosts/codebuddy/host-descriptor.json +5 -0
- package/package.json +4 -4
- package/platform-manifest.json +2 -2
- package/references/02-project-config.md +7 -1
- package/schemas/release-project.schema.json +1 -1
- package/src/commands/verify.mjs +47 -9
- package/src/core/release-metadata.mjs +51 -3
- package/src/producers/foundation-resource-projection.mjs +3 -3
- package/src/schemas/engineering-baseline.schema.json +77 -0
- package/src/schemas/host-descriptor.schema.json +9 -2
package/bin/rules.json
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
"displayName": "CodeBuddy",
|
|
6
6
|
"support": "manual",
|
|
7
7
|
"maturity": "manual",
|
|
8
|
+
"verification": {
|
|
9
|
+
"driverId": "codebuddy-print-v1",
|
|
10
|
+
"authStrategy": "existing-user-state",
|
|
11
|
+
"credentialMutation": "host-managed"
|
|
12
|
+
},
|
|
8
13
|
"sourceAliases": [],
|
|
9
14
|
"pathCategories": [],
|
|
10
15
|
"probeCapabilities": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-skill",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.11",
|
|
4
4
|
"description": "Safe preparation and frozen GitHub/npm production publishing with full happy end verification",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "广州市风荷科技有限公司"
|
|
@@ -78,9 +78,9 @@
|
|
|
78
78
|
"ajv-formats": "3.0.1",
|
|
79
79
|
"libnpmpublish": "11.2.0",
|
|
80
80
|
"npm-registry-fetch": "18.0.2",
|
|
81
|
-
"skill-family-contracts": "0.
|
|
82
|
-
"skill-family-engineering-kit": "0.
|
|
83
|
-
"skill-family-harness-node": "0.
|
|
81
|
+
"skill-family-contracts": "0.17.0",
|
|
82
|
+
"skill-family-engineering-kit": "0.17.0",
|
|
83
|
+
"skill-family-harness-node": "0.17.0",
|
|
84
84
|
"yaml": "2.9.0"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
package/platform-manifest.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
3
|
"platformId": "release-skill",
|
|
4
4
|
"platformName": "release-skill Plugin Platform",
|
|
5
|
-
"version": "0.9.
|
|
5
|
+
"version": "0.9.11",
|
|
6
6
|
"logicalRoot": "skills-src/",
|
|
7
7
|
"logicalRootDigest": "aec96745b30289ed48d576fbfc98ecd3aacb834f83394be76d4734d7d0fc0ad4",
|
|
8
8
|
"projectionDigest": "e5117d89c9f965e15a1464cc84f542cb1e75a685f842183d0cfc7a105ace5ceb",
|
|
9
|
-
"projectionId": "release-skill:platform:0.9.
|
|
9
|
+
"projectionId": "release-skill:platform:0.9.11",
|
|
10
10
|
"manifestRequired": true,
|
|
11
11
|
"projectionSources": {
|
|
12
12
|
"skills-src-root": {
|
|
@@ -42,7 +42,7 @@ releaseUnits: # 发布单元数组,至少 1 个
|
|
|
42
42
|
version:
|
|
43
43
|
source: <string> # 版本来源,如 "package.json"
|
|
44
44
|
tagTemplate: <string> # tag 模板,如 "artifact-graph-v{version}"
|
|
45
|
-
distributions: #
|
|
45
|
+
distributions: # 必填;分发渠道数组,也可显式设为 []
|
|
46
46
|
- type: <string> # "npm" | "claude-plugin" | "codex-plugin"
|
|
47
47
|
package: <string> # npm 包名(type 为 npm 时必填)
|
|
48
48
|
# 插件渠道(claude-plugin/codex-plugin/kimi-plugin/codebuddy-plugin)
|
|
@@ -112,6 +112,12 @@ policy: # 可选,安全策略
|
|
|
112
112
|
forbiddenContentPatterns: [<string>]
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
`distributions: []` 表示该发布单元不生成 npm 或插件市场动作,不表示跳过公开发布。
|
|
116
|
+
生产模式的 `prepare` 仍会冻结 GitHub 快照,并生成 `push-snapshot`、`create-tag` 和
|
|
117
|
+
`github-release`。该单元的 `postPublish` 声明保持独立生效,其中 phase 为
|
|
118
|
+
`postVerify` 的 hook 也不受影响。因此纯插件可以先验证公开 GitHub Release,再向中央
|
|
119
|
+
Hub 投递登记提案。
|
|
120
|
+
|
|
115
121
|
`publicSourceAuthorityReceipt` 只适用于 production prepare。`coordinatorUnitId`
|
|
116
122
|
指定承载该文件的 GitHub Release;`subjectUnitIds` 必须引用现有 release unit,且每个
|
|
117
123
|
unit 恰好声明一个 npm distribution。prepare 等所有 subject tarball 冻结后生成
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
},
|
|
156
156
|
"distributions": {
|
|
157
157
|
"type": "array",
|
|
158
|
-
"
|
|
158
|
+
"description": "Distribution-specific publish and consumer checks. An explicit empty array publishes only the release unit's GitHub snapshot, tag, and GitHub Release; postPublish declarations, including postVerify-phase hooks, remain independent.",
|
|
159
159
|
"items": {
|
|
160
160
|
"type": "object",
|
|
161
161
|
"required": [
|
package/src/commands/verify.mjs
CHANGED
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
isWorktreeFileClean,
|
|
65
65
|
commitBaselineAdvance,
|
|
66
66
|
} from '../core/baseline-advance.mjs';
|
|
67
|
+
import { updatePreviousPublicBaselines } from '../core/release-metadata.mjs';
|
|
67
68
|
import { loadProjectConfig } from '../core/config.mjs';
|
|
68
69
|
import { assertTransition, PUBLISHED, VERIFIED } from '../core/state-machine.mjs';
|
|
69
70
|
import { clearFrozenMarker } from '../core/frozen-marker.mjs';
|
|
@@ -2330,17 +2331,41 @@ export async function verifyRelease(options) {
|
|
|
2330
2331
|
// =======================================================================
|
|
2331
2332
|
let baselineAdvance = null;
|
|
2332
2333
|
const baselineAdvances = deriveBaselineAdvances(plan);
|
|
2333
|
-
|
|
2334
|
+
const hasFirstReleaseBaseline = (plan.units ?? [])
|
|
2335
|
+
.some((unit) => unit?.previousPublicBaseline?.mode === 'none');
|
|
2336
|
+
if (hasFirstReleaseBaseline || baselineAdvances.length > 0) {
|
|
2334
2337
|
try {
|
|
2335
2338
|
const configAbs = configPathOpt
|
|
2336
2339
|
? (isAbsolute(configPathOpt) ? configPathOpt : join(root, configPathOpt))
|
|
2337
2340
|
: join(root, '.release-skill/project.yaml');
|
|
2338
2341
|
const cleanBefore = await isWorktreeFileClean({ root, filePath: configAbs, execFn });
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2342
|
+
// A first-release plan must convert mode=none to a fully bound
|
|
2343
|
+
// baseline. The metadata updater processes the whole plan, so mixed
|
|
2344
|
+
// none+bound plans take this branch exclusively and do not omit or
|
|
2345
|
+
// double-write their already-bound units. Pure bound plans retain
|
|
2346
|
+
// the existing derive/apply path unchanged.
|
|
2347
|
+
let applyResult;
|
|
2348
|
+
if (hasFirstReleaseBaseline) {
|
|
2349
|
+
await loadProjectConfig({ root, configPath: configAbs });
|
|
2350
|
+
const metadataResult = await updatePreviousPublicBaselines({
|
|
2351
|
+
root,
|
|
2352
|
+
planPath,
|
|
2353
|
+
configPath: configAbs,
|
|
2354
|
+
validateFn: async () => { await loadProjectConfig({ root, configPath: configAbs }); },
|
|
2355
|
+
});
|
|
2356
|
+
applyResult = {
|
|
2357
|
+
changed: metadataResult.status === 'UPDATED',
|
|
2358
|
+
updatedUnits: metadataResult.status === 'UPDATED'
|
|
2359
|
+
? metadataResult.units.map((unit) => unit.id)
|
|
2360
|
+
: [],
|
|
2361
|
+
};
|
|
2362
|
+
} else {
|
|
2363
|
+
applyResult = await applyBaselineAdvances({
|
|
2364
|
+
configPath: configAbs,
|
|
2365
|
+
advances: baselineAdvances,
|
|
2366
|
+
validateFn: async () => { await loadProjectConfig({ root, configPath: configAbs }); },
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2344
2369
|
baselineAdvance = { ...applyResult, committed: false };
|
|
2345
2370
|
if (applyResult.changed && cleanBefore) {
|
|
2346
2371
|
const versionLabel = (plan.units ?? [])
|
|
@@ -2362,12 +2387,25 @@ export async function verifyRelease(options) {
|
|
|
2362
2387
|
committed: baselineAdvance.committed,
|
|
2363
2388
|
});
|
|
2364
2389
|
} catch (err) {
|
|
2365
|
-
|
|
2390
|
+
const errorDetails = err instanceof ReleaseError
|
|
2391
|
+
? err.toJSON().details
|
|
2392
|
+
: undefined;
|
|
2393
|
+
baselineAdvance = {
|
|
2394
|
+
failed: true,
|
|
2395
|
+
error: err.message,
|
|
2396
|
+
...(errorDetails ? { details: errorDetails } : {}),
|
|
2397
|
+
};
|
|
2366
2398
|
await evidence.append({
|
|
2367
2399
|
phase: 'verify',
|
|
2368
|
-
step: 'baseline-advance',
|
|
2369
2400
|
status: 'failed',
|
|
2370
|
-
error: {
|
|
2401
|
+
error: {
|
|
2402
|
+
code: err.code,
|
|
2403
|
+
message: err.message,
|
|
2404
|
+
},
|
|
2405
|
+
details: {
|
|
2406
|
+
step: 'baseline-advance',
|
|
2407
|
+
...(errorDetails ? { errorDetails } : {}),
|
|
2408
|
+
},
|
|
2371
2409
|
});
|
|
2372
2410
|
}
|
|
2373
2411
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { lstat, readFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
2
|
+
import { isAbsolute, relative, resolve, sep } from 'node:path';
|
|
3
3
|
import YAML from 'yaml';
|
|
4
4
|
import { replaceFileAtomic } from 'skill-family-harness-node';
|
|
5
5
|
|
|
@@ -20,7 +20,20 @@ function assertOid(value, label) {
|
|
|
20
20
|
export async function updatePreviousPublicBaselines(options = {}) {
|
|
21
21
|
const root = resolve(options.root ?? process.cwd());
|
|
22
22
|
const planPath = resolve(options.planPath ?? '');
|
|
23
|
-
const configPath =
|
|
23
|
+
const configPath = isAbsolute(options.configPath ?? '')
|
|
24
|
+
? resolve(options.configPath)
|
|
25
|
+
: resolve(root, options.configPath ?? '.release-skill/project.yaml');
|
|
26
|
+
const configRelativePath = relative(root, configPath);
|
|
27
|
+
if (
|
|
28
|
+
configRelativePath === '..'
|
|
29
|
+
|| configRelativePath.startsWith(`..${sep}`)
|
|
30
|
+
|| isAbsolute(configRelativePath)
|
|
31
|
+
) {
|
|
32
|
+
throw new ReleaseError(CONFIG_INVALID, 'project config must stay within the project root', {
|
|
33
|
+
root,
|
|
34
|
+
configPath,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
24
37
|
let plan;
|
|
25
38
|
let configRaw;
|
|
26
39
|
let configStat;
|
|
@@ -69,6 +82,7 @@ export async function updatePreviousPublicBaselines(options = {}) {
|
|
|
69
82
|
const old = configUnit.get('previousPublicBaseline', true)?.toJSON?.() ?? {};
|
|
70
83
|
const next = {
|
|
71
84
|
mode: 'bound',
|
|
85
|
+
...(typeof old.githubHost === 'string' ? { githubHost: old.githubHost } : {}),
|
|
72
86
|
repo: old.repo ?? unit.publicRepo,
|
|
73
87
|
ref: old.ref ?? `refs/heads/${frozen.branch}`,
|
|
74
88
|
commit: frozen.commit,
|
|
@@ -78,6 +92,15 @@ export async function updatePreviousPublicBaselines(options = {}) {
|
|
|
78
92
|
if (!next.repo || !next.ref) {
|
|
79
93
|
throw new ReleaseError(GATE_FAILED, `unit "${unit.id}" cannot derive its next public baseline identity`);
|
|
80
94
|
}
|
|
95
|
+
const changed = [
|
|
96
|
+
'mode',
|
|
97
|
+
'repo',
|
|
98
|
+
'ref',
|
|
99
|
+
'commit',
|
|
100
|
+
'tree',
|
|
101
|
+
'manifestDigest',
|
|
102
|
+
].some((field) => old[field] !== next[field]);
|
|
103
|
+
if (!changed) continue;
|
|
81
104
|
configUnit.set('previousPublicBaseline', next);
|
|
82
105
|
updates.push({
|
|
83
106
|
id: unit.id,
|
|
@@ -86,16 +109,41 @@ export async function updatePreviousPublicBaselines(options = {}) {
|
|
|
86
109
|
});
|
|
87
110
|
}
|
|
88
111
|
|
|
112
|
+
if (updates.length === 0) {
|
|
113
|
+
return { status: 'UNCHANGED', configPath, units: [] };
|
|
114
|
+
}
|
|
89
115
|
const nextRaw = doc.toString();
|
|
90
116
|
if (nextRaw === configRaw) {
|
|
91
117
|
return { status: 'UNCHANGED', configPath, units: updates };
|
|
92
118
|
}
|
|
93
119
|
try {
|
|
94
|
-
await replaceFileAtomic(root,
|
|
120
|
+
await replaceFileAtomic(root, configRelativePath, nextRaw, {
|
|
95
121
|
mode: configStat.mode & 0o777,
|
|
96
122
|
});
|
|
97
123
|
} catch (error) {
|
|
98
124
|
throw new ReleaseError(CONFIG_INVALID, `cannot update project release metadata: ${error.message}`, error.details);
|
|
99
125
|
}
|
|
126
|
+
if (typeof options.validateFn === 'function') {
|
|
127
|
+
try {
|
|
128
|
+
await options.validateFn(configPath);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
try {
|
|
131
|
+
await replaceFileAtomic(root, configRelativePath, configRaw, {
|
|
132
|
+
mode: configStat.mode & 0o777,
|
|
133
|
+
});
|
|
134
|
+
} catch (restoreError) {
|
|
135
|
+
throw new ReleaseError(
|
|
136
|
+
CONFIG_INVALID,
|
|
137
|
+
`cannot restore project release metadata after validation failed: ${restoreError.message}`,
|
|
138
|
+
{ validationError: error.message, restoreError: restoreError.details },
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
throw new ReleaseError(
|
|
142
|
+
GATE_FAILED,
|
|
143
|
+
`baseline advance reverted: rewritten config failed validation: ${error.message}`,
|
|
144
|
+
{ configPath, cause: error.message },
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
100
148
|
return { status: 'UPDATED', configPath, units: updates };
|
|
101
149
|
}
|
|
@@ -55,9 +55,9 @@ import { digestBytes, publishFileOrReplace, readFileStrict, withTemporaryWorkspa
|
|
|
55
55
|
import { canonicalJson } from '../core/digest.mjs';
|
|
56
56
|
|
|
57
57
|
export const FOUNDATION_PACKAGES = Object.freeze({
|
|
58
|
-
'skill-family-contracts': '0.
|
|
59
|
-
'skill-family-engineering-kit': '0.
|
|
60
|
-
'skill-family-harness-node': '0.
|
|
58
|
+
'skill-family-contracts': '0.17.0',
|
|
59
|
+
'skill-family-engineering-kit': '0.17.0',
|
|
60
|
+
'skill-family-harness-node': '0.17.0',
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
export const BINDING_RECORD_PATH = 'bin/foundation-resource-binding.json';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://contracts.skill-family.example/v1/engineering-baseline.json",
|
|
4
|
+
"title": "EngineeringBaseline",
|
|
5
|
+
"description": "Business-neutral identity for an engineering baseline. The contract carries the provider-owned baseline identity, canonical rule lineage references, and the Foundation reference implementation identity; it does not carry rule bodies, effects, equivalence, or exemption semantics.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schemaVersion",
|
|
10
|
+
"kind",
|
|
11
|
+
"provider",
|
|
12
|
+
"id",
|
|
13
|
+
"version",
|
|
14
|
+
"digest",
|
|
15
|
+
"canonicalRuleRefs",
|
|
16
|
+
"referenceImplementation"
|
|
17
|
+
],
|
|
18
|
+
"properties": {
|
|
19
|
+
"schemaVersion": { "const": 1 },
|
|
20
|
+
"kind": { "const": "skill-family.engineering-baseline" },
|
|
21
|
+
"provider": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1,
|
|
24
|
+
"description": "Provider that owns the baseline identity, for example an independent Audit implementation."
|
|
25
|
+
},
|
|
26
|
+
"id": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"minLength": 1,
|
|
29
|
+
"description": "Provider-scoped stable baseline identifier."
|
|
30
|
+
},
|
|
31
|
+
"version": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$",
|
|
34
|
+
"description": "Semantic version of the provider-owned baseline identity."
|
|
35
|
+
},
|
|
36
|
+
"digest": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"pattern": "^[0-9a-f]{64}$",
|
|
39
|
+
"description": "SHA-256 digest of the canonical JSON of this document with digest omitted."
|
|
40
|
+
},
|
|
41
|
+
"canonicalRuleRefs": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"minItems": 1,
|
|
44
|
+
"items": { "$ref": "#/$defs/canonicalRuleRef" },
|
|
45
|
+
"description": "Sorted, unique references to provider-owned canonical rule lineages. Rule bodies and decisions remain outside this contract."
|
|
46
|
+
},
|
|
47
|
+
"referenceImplementation": {
|
|
48
|
+
"$ref": "#/$defs/referenceImplementation",
|
|
49
|
+
"description": "Identity of the Foundation reference implementation used by the baseline provider."
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"$defs": {
|
|
53
|
+
"canonicalRuleRef": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": false,
|
|
56
|
+
"required": ["id", "revision", "revisionDigest"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"id": { "type": "string", "minLength": 1 },
|
|
59
|
+
"revision": { "type": "integer", "minimum": 1 },
|
|
60
|
+
"revisionDigest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"referenceImplementation": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"additionalProperties": false,
|
|
66
|
+
"required": ["foundationVersion", "profile", "skeletonDigest"],
|
|
67
|
+
"properties": {
|
|
68
|
+
"foundationVersion": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
|
|
71
|
+
},
|
|
72
|
+
"profile": { "type": "string", "minLength": 1 },
|
|
73
|
+
"skeletonDigest": { "type": "string", "pattern": "^[0-9a-f]{64}$" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"additionalProperties": false,
|
|
26
26
|
"required": ["driverId", "authStrategy", "credentialMutation"],
|
|
27
27
|
"properties": {
|
|
28
|
-
"driverId": { "enum": ["kimi-code-print-v1", "workbuddy-codebuddy-print-v1", "claude-code-print-v1", "codex-exec-v1", "qodercli-print-v1"] },
|
|
28
|
+
"driverId": { "enum": ["kimi-code-print-v1", "workbuddy-codebuddy-print-v1", "codebuddy-print-v1", "claude-code-print-v1", "codex-exec-v1", "qodercli-print-v1"] },
|
|
29
29
|
"authStrategy": { "const": "existing-user-state" },
|
|
30
30
|
"credentialMutation": { "const": "host-managed" }
|
|
31
31
|
}
|
|
@@ -80,6 +80,13 @@
|
|
|
80
80
|
"properties": { "verification": { "type": "object", "properties": { "driverId": { "const": "workbuddy-codebuddy-print-v1" } } } }
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
|
+
{
|
|
84
|
+
"if": { "properties": { "hostId": { "const": "codebuddy" } }, "required": ["hostId"] },
|
|
85
|
+
"then": {
|
|
86
|
+
"required": ["verification"],
|
|
87
|
+
"properties": { "verification": { "type": "object", "properties": { "driverId": { "const": "codebuddy-print-v1" } } } }
|
|
88
|
+
}
|
|
89
|
+
},
|
|
83
90
|
{
|
|
84
91
|
"if": { "properties": { "hostId": { "const": "claude" } }, "required": ["hostId"] },
|
|
85
92
|
"then": {
|
|
@@ -102,7 +109,7 @@
|
|
|
102
109
|
}
|
|
103
110
|
},
|
|
104
111
|
{
|
|
105
|
-
"if": { "properties": { "hostId": { "enum": ["kimi-code", "workbuddy", "claude", "codex", "qoder"] } }, "required": ["hostId"] },
|
|
112
|
+
"if": { "properties": { "hostId": { "enum": ["kimi-code", "workbuddy", "codebuddy", "claude", "codex", "qoder"] } }, "required": ["hostId"] },
|
|
106
113
|
"else": { "properties": { "verification": false } }
|
|
107
114
|
},
|
|
108
115
|
{
|