@openspecui/core 4.1.0 → 6.0.0-beta.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/dist/cli-projection-DxnVGm2B.d.mts +789 -0
- package/dist/cli-projection-vO3-FJg5.mjs +161 -0
- package/dist/cli-projection.d.mts +6 -0
- package/dist/cli-projection.mjs +4 -0
- package/dist/command-result-fkH3Ekdz.d.mts +8477 -0
- package/dist/common-D8YUK9dA.mjs +57 -0
- package/dist/dashboard-summary-transport-CQ4is5_e.d.mts +66227 -0
- package/dist/dashboard-summary-transport-D2VBAIxg.mjs +175 -0
- package/dist/dashboard-summary-transport.d.mts +25 -0
- package/dist/dashboard-summary-transport.mjs +6 -0
- package/dist/{document-translation-D4YK18I3.mjs → document-translation-CeJFGMoy.mjs} +1 -1
- package/dist/{document-translation-CIPGsZD8.d.mts → document-translation-D50BnvVh.d.mts} +100 -100
- package/dist/document-translation.d.mts +1 -1
- package/dist/document-translation.mjs +2 -2
- package/dist/{hosted-app-CzMRiEgY.mjs → hosted-app-BPU4OR41.mjs} +31 -9
- package/dist/hosted-app.d.mts +25 -2
- package/dist/hosted-app.mjs +7 -2
- package/dist/hosted-contract-CcRnb51e.mjs +234 -0
- package/dist/hosted-contract.d.mts +25 -0
- package/dist/hosted-contract.mjs +7 -0
- package/dist/index.d.mts +25 -2686
- package/dist/index.mjs +2114 -1098
- package/dist/{local-download-profiles-B30HrSO2.d.mts → local-download-profiles-BL_rtlVM.d.mts} +1 -1
- package/dist/local-download-profiles.d.mts +2 -2
- package/dist/local-download-profiles.mjs +1 -1
- package/dist/markdown-facts.d.mts +1 -1
- package/dist/markdown-facts.mjs +1 -1
- package/dist/{markdown-reading-CgXuXp6s.d.mts → markdown-reading-LUdqfbxH.d.mts} +1 -1
- package/dist/{markdown-reading-DdcB7run.mjs → markdown-reading-mG4OAbDO.mjs} +1 -1
- package/dist/markdown-reading.d.mts +2 -2
- package/dist/markdown-reading.mjs +2 -2
- package/dist/{notifications-AKAcmeKT.mjs → notifications-C2bxAzX_.mjs} +13 -2
- package/dist/{notifications-HYH-lklF.d.mts → notifications-CgJlLgLO.d.mts} +34 -8
- package/dist/notifications.d.mts +2 -2
- package/dist/notifications.mjs +3 -3
- package/dist/{openspec-annotations-CeXd0JIZ.d.mts → openspec-annotations-C58Aoi-V.d.mts} +2 -2
- package/dist/{openspec-annotations-D_6Pz7k4.mjs → openspec-annotations-DCfqBMal.mjs} +2 -2
- package/dist/openspec-annotations.d.mts +3 -3
- package/dist/openspec-annotations.mjs +3 -3
- package/dist/openspec-compat.d.mts +18 -11
- package/dist/openspec-compat.mjs +22 -14
- package/dist/{openspec-projection-B8s-KWQ7.mjs → openspec-projection-DCgToo0Q.mjs} +2 -2
- package/dist/{openspec-projection-BphzrwYP.d.mts → openspec-projection-RohNZI4p.d.mts} +3 -3
- package/dist/openspec-projection.d.mts +5 -5
- package/dist/openspec-projection.mjs +4 -4
- package/dist/opsx-display-path.d.mts +1 -1
- package/dist/opsx-display-path.mjs +1 -1
- package/dist/{opsx-entity-CFUCqev8.d.mts → opsx-entity-D7kDQsze.d.mts} +2 -2
- package/dist/opsx-entity.d.mts +7 -3
- package/dist/opsx-entity.mjs +1 -1
- package/dist/{opsx-schema-detail-DXKXqMQa.d.mts → opsx-schema-detail-BxDXEwDY.d.mts} +2 -2
- package/dist/opsx-schema-detail.d.mts +8 -4
- package/dist/opsx-schema-detail.mjs +1 -1
- package/dist/opsx-types-BJ8AjhrS.d.mts +3642 -0
- package/dist/opsx-workflows-BvnJqjfL.d.mts +36 -0
- package/dist/opsx-workflows-Ccc6U7IR.mjs +89 -0
- package/dist/opsx-workflows.d.mts +2 -0
- package/dist/opsx-workflows.mjs +3 -0
- package/dist/planning-cli-projection-DIRxeq2H.mjs +421 -0
- package/dist/planning-cli-projection.d.mts +25 -0
- package/dist/planning-cli-projection.mjs +9 -0
- package/dist/schemas-BFroDdOC.mjs +287 -0
- package/dist/{schemas-CNKCVc7m.d.mts → schemas-DS-JqAJ2.d.mts} +498 -52
- package/dist/{sounds-J6z7o4mt.d.mts → sounds-qhRgCy0F.d.mts} +5 -5
- package/dist/sounds.d.mts +1 -1
- package/dist/sounds.mjs +1 -1
- package/dist/spec-catalog-ZGuiZ4CE.mjs +901 -0
- package/dist/spec-catalog.d.mts +25 -0
- package/dist/spec-catalog.mjs +6 -0
- package/dist/store-mutation-protocol-5tfs-RmD.d.mts +727 -0
- package/dist/store-mutation-protocol-CSwD-xPO.mjs +63 -0
- package/dist/store-mutation-protocol.d.mts +2 -0
- package/dist/store-mutation-protocol.mjs +4 -0
- package/dist/{store-types-Cu41QSww.mjs → store-types-DlX1REBg.mjs} +39 -18
- package/dist/{store-types-BiE-Ey--.d.mts → store-types-b554wAQJ.d.mts} +22 -12
- package/dist/store-types.d.mts +6 -2
- package/dist/store-types.mjs +2 -2
- package/dist/task-progress-B_IWVXjA.mjs +216 -0
- package/dist/task-progress.d.mts +7 -4
- package/dist/task-progress.mjs +3 -3
- package/dist/{terminal-audio-TBoU2jSK.mjs → terminal-audio-d6KItUeJ.mjs} +1 -1
- package/dist/{terminal-audio-BeUXlQgj.d.mts → terminal-audio-tXDm_EDe.d.mts} +2 -2
- package/dist/terminal-audio.d.mts +2 -2
- package/dist/terminal-audio.mjs +2 -2
- package/dist/terminal-control.d.mts +2 -2
- package/dist/terminal-control.mjs +1 -1
- package/dist/{terminal-invocation-ClVh0HeM.d.mts → terminal-invocation-BOvxThym.d.mts} +203 -84
- package/dist/terminal-invocation.d.mts +1 -1
- package/dist/terminal-invocation.mjs +1 -1
- package/dist/terminal-theme.d.mts +1 -1
- package/dist/terminal-theme.mjs +1 -1
- package/dist/translation-language-pair.d.mts +1 -1
- package/dist/translation-language-pair.mjs +1 -1
- package/dist/{translator-D6t_LEVN.d.mts → translator-NKv1wo3o.d.mts} +208 -208
- package/dist/translator.d.mts +1 -1
- package/dist/translator.mjs +1 -1
- package/package.json +55 -7
- package/dist/hosted-app-DHs94gIR.d.mts +0 -43
- package/dist/opsx-types-2rgsQHsB.d.mts +0 -402
- package/dist/task-progress-BHn4bCoD.d.mts +0 -24
- package/dist/task-progress-DhHYHnTv.mjs +0 -70
- /package/dist/{local-download-profiles-kpNEcdF_.mjs → local-download-profiles-odzOdf96.mjs} +0 -0
- /package/dist/{markdown-facts-BBCTe_qq.mjs → markdown-facts-BUqLvFRf.mjs} +0 -0
- /package/dist/{markdown-facts-Dk7FKaaT.d.mts → markdown-facts-CCw3QdbM.d.mts} +0 -0
- /package/dist/{opsx-display-path-CUCOrHcM.mjs → opsx-display-path-D13XV20v.mjs} +0 -0
- /package/dist/{opsx-display-path-cIMKa1aw.d.mts → opsx-display-path-RXS5JTbV.d.mts} +0 -0
- /package/dist/{opsx-entity-c7m5CbgU.mjs → opsx-entity-Cn_Zu1J3.mjs} +0 -0
- /package/dist/{opsx-schema-detail-BH82X6aU.mjs → opsx-schema-detail-Beis4Ba2.mjs} +0 -0
- /package/dist/{sounds-CB3ubSnj.mjs → sounds-NXwveBqq.mjs} +0 -0
- /package/dist/{terminal-control-VpTuh17B.mjs → terminal-control-BSAlOTs8.mjs} +0 -0
- /package/dist/{terminal-invocation-C2MCNBhK.mjs → terminal-invocation-0p-j2eSP.mjs} +0 -0
- /package/dist/{terminal-theme-cevliJw2.mjs → terminal-theme-B8iRttTR.mjs} +0 -0
- /package/dist/{terminal-theme-hvQjTsNh.d.mts → terminal-theme-m3MSGJ7U.d.mts} +0 -0
- /package/dist/{translation-language-pair-DZ_WNp_M.mjs → translation-language-pair-Bbhk-LAC.mjs} +0 -0
- /package/dist/{translation-language-pair-DmaOfHqD.d.mts → translation-language-pair-C18GPATW.d.mts} +0 -0
- /package/dist/{translator-DbUT1Ayn.mjs → translator-Cjtv4tya.mjs} +0 -0
|
@@ -0,0 +1,901 @@
|
|
|
1
|
+
import { l as SpecSchema } from "./schemas-BFroDdOC.mjs";
|
|
2
|
+
import { a as CliRootSchema, i as CliReferenceIndexEntrySchema, n as CliDiagnosticSchema, r as CliDoctorReferenceEntrySchema, t as CliDiagnosticFailureSchema } from "./common-D8YUK9dA.mjs";
|
|
3
|
+
import { r as CliProjectionCommandEvidenceSchema } from "./cli-projection-vO3-FJg5.mjs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { match } from "ts-pattern";
|
|
6
|
+
|
|
7
|
+
//#region src/cli-contracts/command-result.ts
|
|
8
|
+
/**
|
|
9
|
+
* Orthogonal intents (created 2026-07-15 Asia/Shanghai):
|
|
10
|
+
* 1. Preserve every process-level fact from an OpenSpec CLI invocation.
|
|
11
|
+
* 2. Validate command payloads without discarding the raw JSON document.
|
|
12
|
+
* 3. Surface contract drift separately from CLI command failure.
|
|
13
|
+
*
|
|
14
|
+
* Original request (2026-07-15): "对新增字段保持可扩展,对必需语义严格验证。"
|
|
15
|
+
*/
|
|
16
|
+
function formatContractError(error) {
|
|
17
|
+
return error.issues.map((issue) => {
|
|
18
|
+
return `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`;
|
|
19
|
+
}).join("; ");
|
|
20
|
+
}
|
|
21
|
+
function extractDiagnostics(payload) {
|
|
22
|
+
if (typeof payload !== "object" || payload === null || !("status" in payload)) return [];
|
|
23
|
+
const parsed = z.array(CliDiagnosticSchema).safeParse(payload.status);
|
|
24
|
+
return parsed.success ? parsed.data : [];
|
|
25
|
+
}
|
|
26
|
+
/** Parse one CLI JSON document while retaining all process and raw-payload evidence. */
|
|
27
|
+
function parseCliCommandResult(result, schema) {
|
|
28
|
+
let payload;
|
|
29
|
+
try {
|
|
30
|
+
payload = JSON.parse(result.stdout);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
33
|
+
return {
|
|
34
|
+
...result,
|
|
35
|
+
data: null,
|
|
36
|
+
payload: null,
|
|
37
|
+
diagnostics: [],
|
|
38
|
+
contractError: `OpenSpec CLI stdout is not one JSON document: ${message}`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const parsed = schema.safeParse(payload);
|
|
42
|
+
if (!parsed.success) return {
|
|
43
|
+
...result,
|
|
44
|
+
data: null,
|
|
45
|
+
payload,
|
|
46
|
+
diagnostics: extractDiagnostics(payload),
|
|
47
|
+
contractError: formatContractError(parsed.error)
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
...result,
|
|
51
|
+
data: parsed.data,
|
|
52
|
+
payload,
|
|
53
|
+
diagnostics: extractDiagnostics(parsed.data)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/cli-contracts/store.ts
|
|
59
|
+
/**
|
|
60
|
+
* Orthogonal intents (created 2026-07-15 Asia/Shanghai):
|
|
61
|
+
* 1. Model the snake_case Store command family.
|
|
62
|
+
* 2. Model root Doctor and Context relationship projections.
|
|
63
|
+
* 3. Preserve healthy empty Stores and diagnostic failure null-shapes.
|
|
64
|
+
*
|
|
65
|
+
* Original request (2026-07-15): "Store/Context/Doctor 的 snake_case 与 workflow 的 camelCase 必须按官方合同处理。"
|
|
66
|
+
*/
|
|
67
|
+
/** Registered Store identity and canonical root emitted by the CLI. */
|
|
68
|
+
const CliStoreSchema = z.object({
|
|
69
|
+
id: z.string(),
|
|
70
|
+
root: z.string(),
|
|
71
|
+
metadata_path: z.string().optional()
|
|
72
|
+
}).passthrough();
|
|
73
|
+
/** Strict typed result of the CLI Store-list JSON command. */
|
|
74
|
+
const CliStoreListSchema = z.object({
|
|
75
|
+
stores: z.array(CliStoreSchema),
|
|
76
|
+
status: z.array(CliDiagnosticSchema)
|
|
77
|
+
}).passthrough();
|
|
78
|
+
const CliStoreRegistryMutationSchema = z.object({
|
|
79
|
+
path: z.string(),
|
|
80
|
+
registered: z.boolean(),
|
|
81
|
+
already_registered: z.boolean()
|
|
82
|
+
}).passthrough();
|
|
83
|
+
const CliStoreGitMutationSchema = z.object({
|
|
84
|
+
is_repository: z.boolean(),
|
|
85
|
+
initialized: z.boolean(),
|
|
86
|
+
committed: z.boolean()
|
|
87
|
+
}).passthrough();
|
|
88
|
+
/** Strict Store setup/register mutation result. */
|
|
89
|
+
const CliStoreMutationSchema = z.object({
|
|
90
|
+
store: CliStoreSchema.nullable(),
|
|
91
|
+
registry: CliStoreRegistryMutationSchema.nullable(),
|
|
92
|
+
git: CliStoreGitMutationSchema.nullable(),
|
|
93
|
+
created_files: z.array(z.string()),
|
|
94
|
+
status: z.array(CliDiagnosticSchema)
|
|
95
|
+
}).passthrough();
|
|
96
|
+
const CliStoreRegistryCleanupSchema = z.object({
|
|
97
|
+
path: z.string(),
|
|
98
|
+
removed: z.boolean()
|
|
99
|
+
}).passthrough();
|
|
100
|
+
const CliStoreFilesCleanupSchema = z.object({
|
|
101
|
+
deleted: z.boolean(),
|
|
102
|
+
deleted_path: z.string().nullable(),
|
|
103
|
+
left_on_disk: z.string().nullable()
|
|
104
|
+
}).passthrough();
|
|
105
|
+
/** Strict Store unregister/remove cleanup result. */
|
|
106
|
+
const CliStoreCleanupSchema = z.object({
|
|
107
|
+
store: CliStoreSchema.nullable(),
|
|
108
|
+
registry: CliStoreRegistryCleanupSchema.nullable(),
|
|
109
|
+
files: CliStoreFilesCleanupSchema.nullable(),
|
|
110
|
+
status: z.array(CliDiagnosticSchema)
|
|
111
|
+
}).passthrough();
|
|
112
|
+
const CliPresenceSchema = z.object({ present: z.boolean().nullable() }).passthrough();
|
|
113
|
+
const CliOpenSpecRootInspectionSchema = z.object({
|
|
114
|
+
present: z.boolean().nullable(),
|
|
115
|
+
config: CliPresenceSchema,
|
|
116
|
+
specs: CliPresenceSchema,
|
|
117
|
+
changes: CliPresenceSchema,
|
|
118
|
+
archive: CliPresenceSchema,
|
|
119
|
+
healthy: z.boolean(),
|
|
120
|
+
status: z.array(CliDiagnosticSchema)
|
|
121
|
+
}).passthrough();
|
|
122
|
+
const CliStoreMetadataSchema = z.object({
|
|
123
|
+
present: z.boolean().nullable(),
|
|
124
|
+
valid: z.boolean().nullable(),
|
|
125
|
+
id: z.string().nullable().optional(),
|
|
126
|
+
remote: z.string().nullable().optional()
|
|
127
|
+
}).passthrough();
|
|
128
|
+
const CliStoreGitInspectionSchema = z.object({
|
|
129
|
+
is_repository: z.boolean().nullable(),
|
|
130
|
+
has_commits: z.boolean().nullable(),
|
|
131
|
+
has_uncommitted_changes: z.boolean().nullable(),
|
|
132
|
+
has_remote: z.boolean().nullable(),
|
|
133
|
+
origin_url: z.string().nullable()
|
|
134
|
+
}).passthrough();
|
|
135
|
+
/** Strict Doctor facts for one registered Store. */
|
|
136
|
+
const CliStoreDoctorEntrySchema = CliStoreSchema.extend({
|
|
137
|
+
openspec_root: CliOpenSpecRootInspectionSchema,
|
|
138
|
+
metadata: CliStoreMetadataSchema,
|
|
139
|
+
git: CliStoreGitInspectionSchema,
|
|
140
|
+
status: z.array(CliDiagnosticSchema)
|
|
141
|
+
}).passthrough();
|
|
142
|
+
/** Strict typed result of the CLI Store Doctor JSON command. */
|
|
143
|
+
const CliStoreDoctorSchema = z.object({
|
|
144
|
+
stores: z.array(CliStoreDoctorEntrySchema),
|
|
145
|
+
status: z.array(CliDiagnosticSchema)
|
|
146
|
+
}).passthrough();
|
|
147
|
+
const CliDoctorRootSchema = CliRootSchema.extend({
|
|
148
|
+
healthy: z.boolean(),
|
|
149
|
+
status: z.array(CliDiagnosticSchema)
|
|
150
|
+
}).passthrough();
|
|
151
|
+
const CliDoctorStoreSchema = z.object({
|
|
152
|
+
id: z.string(),
|
|
153
|
+
metadata: CliStoreMetadataSchema,
|
|
154
|
+
origin_url: z.string().optional(),
|
|
155
|
+
status: z.array(CliDiagnosticSchema)
|
|
156
|
+
}).passthrough();
|
|
157
|
+
/** Root, Store, Reference, and diagnostic result of CLI Doctor. */
|
|
158
|
+
const CliDoctorSchema = z.object({
|
|
159
|
+
root: CliDoctorRootSchema.nullable(),
|
|
160
|
+
store: CliDoctorStoreSchema.nullable(),
|
|
161
|
+
references: z.array(CliDoctorReferenceEntrySchema),
|
|
162
|
+
status: z.array(CliDiagnosticSchema)
|
|
163
|
+
}).passthrough();
|
|
164
|
+
const CliContextRootSchema = CliRootSchema.extend({ role: z.literal("openspec_root") }).passthrough();
|
|
165
|
+
const CliContextMemberSchema = z.object({
|
|
166
|
+
role: z.literal("referenced_store"),
|
|
167
|
+
id: z.string(),
|
|
168
|
+
path: z.string().optional(),
|
|
169
|
+
remote: z.string().optional(),
|
|
170
|
+
fetch: z.string().optional(),
|
|
171
|
+
status: z.array(CliDiagnosticSchema)
|
|
172
|
+
}).passthrough();
|
|
173
|
+
/** Root and direct referenced-Store relationship result of CLI Context. */
|
|
174
|
+
const CliContextSchema = z.object({
|
|
175
|
+
root: CliContextRootSchema.nullable(),
|
|
176
|
+
members: z.array(CliContextMemberSchema),
|
|
177
|
+
status: z.array(CliDiagnosticSchema)
|
|
178
|
+
}).passthrough();
|
|
179
|
+
/** Known JSON documents that a Store-family command may emit on failure. */
|
|
180
|
+
const CliStoreCommandFailureSchema = z.union([
|
|
181
|
+
CliStoreMutationSchema,
|
|
182
|
+
CliStoreCleanupSchema,
|
|
183
|
+
CliStoreListSchema,
|
|
184
|
+
CliStoreDoctorSchema,
|
|
185
|
+
CliDiagnosticFailureSchema
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/cli-contracts/workflow.ts
|
|
190
|
+
/**
|
|
191
|
+
* Orthogonal intents (updated 2026-07-26 Asia/Shanghai):
|
|
192
|
+
* 1. Model camelCase workflow JSON independently from Store-family JSON.
|
|
193
|
+
* 2. Preserve strict validate and archive outcomes, including failure payloads.
|
|
194
|
+
* 3. Preserve multiline requirement bodies from `show --json`.
|
|
195
|
+
* 4. Preserve complete OpenSpec 1.6 Status/Instructions action contracts as CLI facts.
|
|
196
|
+
* 5. Export the successful Spec-document schema for browser-safe projection validation.
|
|
197
|
+
*
|
|
198
|
+
* Original request (2026-07-15): "为不同命令建立强类型适配器,不实现平行解析规则。"
|
|
199
|
+
* Original request (2026-07-26): "展开全面的接口升级和内核升级和测试升级。"
|
|
200
|
+
*/
|
|
201
|
+
const CliChangeListEntrySchema = z.object({
|
|
202
|
+
name: z.string(),
|
|
203
|
+
completedTasks: z.number(),
|
|
204
|
+
totalTasks: z.number(),
|
|
205
|
+
lastModified: z.string(),
|
|
206
|
+
status: z.enum([
|
|
207
|
+
"no-tasks",
|
|
208
|
+
"complete",
|
|
209
|
+
"in-progress"
|
|
210
|
+
])
|
|
211
|
+
}).passthrough();
|
|
212
|
+
/** Typed result of the CLI change-list JSON command. */
|
|
213
|
+
const CliChangeListSchema = z.object({
|
|
214
|
+
changes: z.array(CliChangeListEntrySchema),
|
|
215
|
+
root: CliRootSchema.nullable(),
|
|
216
|
+
status: z.array(CliDiagnosticSchema).optional()
|
|
217
|
+
}).passthrough();
|
|
218
|
+
const CliSpecListEntrySchema = z.object({
|
|
219
|
+
id: z.string(),
|
|
220
|
+
requirementCount: z.number()
|
|
221
|
+
}).passthrough();
|
|
222
|
+
/** Typed result of the CLI Spec-list JSON command. */
|
|
223
|
+
const CliSpecListSchema = z.object({
|
|
224
|
+
specs: z.array(CliSpecListEntrySchema),
|
|
225
|
+
root: CliRootSchema.nullable(),
|
|
226
|
+
status: z.array(CliDiagnosticSchema).optional()
|
|
227
|
+
}).passthrough();
|
|
228
|
+
/** One workflow schema discovered by the CLI-selected OpenSpec runtime. */
|
|
229
|
+
const CliSchemaInfoSchema = z.object({
|
|
230
|
+
name: z.string(),
|
|
231
|
+
description: z.string().optional(),
|
|
232
|
+
artifacts: z.array(z.string()),
|
|
233
|
+
source: z.enum([
|
|
234
|
+
"project",
|
|
235
|
+
"user",
|
|
236
|
+
"package"
|
|
237
|
+
])
|
|
238
|
+
}).passthrough();
|
|
239
|
+
/** Typed result of `openspec schemas --json`. */
|
|
240
|
+
const CliSchemasSchema = z.array(CliSchemaInfoSchema);
|
|
241
|
+
/** CLI resolution for one schema, including lower-priority shadows. */
|
|
242
|
+
const CliSchemaShadowSchema = z.object({
|
|
243
|
+
source: z.enum([
|
|
244
|
+
"project",
|
|
245
|
+
"user",
|
|
246
|
+
"package"
|
|
247
|
+
]),
|
|
248
|
+
path: z.string()
|
|
249
|
+
}).passthrough();
|
|
250
|
+
const CliSchemaResolutionSchema = z.object({
|
|
251
|
+
name: z.string(),
|
|
252
|
+
source: z.enum([
|
|
253
|
+
"project",
|
|
254
|
+
"user",
|
|
255
|
+
"package"
|
|
256
|
+
]),
|
|
257
|
+
path: z.string(),
|
|
258
|
+
shadows: z.array(CliSchemaShadowSchema)
|
|
259
|
+
}).passthrough();
|
|
260
|
+
/** Typed result of `openspec schema which <name> --json`. */
|
|
261
|
+
const CliSchemaWhichSchema = CliSchemaResolutionSchema;
|
|
262
|
+
/** Typed result of `openspec templates --json [--schema <name>]`. */
|
|
263
|
+
const CliTemplateEntrySchema = z.object({
|
|
264
|
+
path: z.string(),
|
|
265
|
+
source: z.enum([
|
|
266
|
+
"project",
|
|
267
|
+
"user",
|
|
268
|
+
"package"
|
|
269
|
+
])
|
|
270
|
+
}).passthrough();
|
|
271
|
+
const CliTemplatesSchema = z.record(CliTemplateEntrySchema);
|
|
272
|
+
const CliSpecRequirementSchema = z.object({
|
|
273
|
+
text: z.string(),
|
|
274
|
+
scenarios: z.array(z.object({ rawText: z.string() }).passthrough())
|
|
275
|
+
}).passthrough();
|
|
276
|
+
/** Typed successful document returned by the CLI show-Spec JSON command. */
|
|
277
|
+
const CliShowSpecDocumentSchema = z.object({
|
|
278
|
+
id: z.string(),
|
|
279
|
+
title: z.string(),
|
|
280
|
+
overview: z.string(),
|
|
281
|
+
requirementCount: z.number(),
|
|
282
|
+
requirements: z.array(CliSpecRequirementSchema),
|
|
283
|
+
metadata: z.object({
|
|
284
|
+
version: z.string(),
|
|
285
|
+
format: z.string(),
|
|
286
|
+
sourcePath: z.string().optional()
|
|
287
|
+
}).passthrough(),
|
|
288
|
+
root: CliRootSchema
|
|
289
|
+
}).passthrough();
|
|
290
|
+
/** Typed success or diagnostic failure result of the CLI show-Spec JSON command. */
|
|
291
|
+
const CliShowSpecSchema = z.union([CliShowSpecDocumentSchema, CliDiagnosticFailureSchema]);
|
|
292
|
+
/** CLI-resolved output and existing paths for one workflow artifact. */
|
|
293
|
+
const CliArtifactPathSchema = z.object({
|
|
294
|
+
outputPath: z.string(),
|
|
295
|
+
resolvedOutputPath: z.string(),
|
|
296
|
+
existingOutputPaths: z.array(z.string())
|
|
297
|
+
}).passthrough();
|
|
298
|
+
/** Repository-local planning home selected by the CLI workflow engine. */
|
|
299
|
+
const CliPlanningHomeSchema = z.object({
|
|
300
|
+
kind: z.literal("repo"),
|
|
301
|
+
root: z.string(),
|
|
302
|
+
changesDir: z.string(),
|
|
303
|
+
defaultSchema: z.string()
|
|
304
|
+
}).passthrough();
|
|
305
|
+
/** CLI-owned action boundaries and edit constraints for a workflow. */
|
|
306
|
+
const CliActionContextSchema = z.object({
|
|
307
|
+
mode: z.literal("repo-local"),
|
|
308
|
+
sourceOfTruth: z.literal("repo"),
|
|
309
|
+
planningArtifacts: z.array(z.string()),
|
|
310
|
+
linkedContext: z.array(z.object({ name: z.string() }).passthrough()),
|
|
311
|
+
allowedEditRoots: z.array(z.string()),
|
|
312
|
+
requiresAffectedAreaSelection: z.boolean(),
|
|
313
|
+
constraints: z.array(z.string())
|
|
314
|
+
}).passthrough();
|
|
315
|
+
const CliStatusArtifactSchema = z.object({
|
|
316
|
+
id: z.string(),
|
|
317
|
+
outputPath: z.string(),
|
|
318
|
+
status: z.enum([
|
|
319
|
+
"done",
|
|
320
|
+
"ready",
|
|
321
|
+
"blocked"
|
|
322
|
+
]),
|
|
323
|
+
missingDeps: z.array(z.string()).optional()
|
|
324
|
+
}).passthrough();
|
|
325
|
+
/** Complete successful Status payload for one OpenSpec change. */
|
|
326
|
+
const CliWorkflowStatusSuccessSchema = z.object({
|
|
327
|
+
changeName: z.string(),
|
|
328
|
+
schemaName: z.string(),
|
|
329
|
+
planningHome: CliPlanningHomeSchema,
|
|
330
|
+
changeRoot: z.string(),
|
|
331
|
+
artifactPaths: z.record(CliArtifactPathSchema),
|
|
332
|
+
isComplete: z.boolean(),
|
|
333
|
+
applyRequires: z.array(z.string()),
|
|
334
|
+
nextSteps: z.array(z.string()),
|
|
335
|
+
actionContext: CliActionContextSchema,
|
|
336
|
+
artifacts: z.array(CliStatusArtifactSchema),
|
|
337
|
+
root: CliRootSchema
|
|
338
|
+
}).passthrough();
|
|
339
|
+
/** Typed success or diagnostic failure result of the CLI Status JSON command. */
|
|
340
|
+
const CliWorkflowStatusSchema = z.union([CliWorkflowStatusSuccessSchema, CliDiagnosticFailureSchema]);
|
|
341
|
+
const CliInstructionDependencySchema = z.object({
|
|
342
|
+
id: z.string(),
|
|
343
|
+
done: z.boolean(),
|
|
344
|
+
path: z.string(),
|
|
345
|
+
description: z.string()
|
|
346
|
+
}).passthrough();
|
|
347
|
+
/** Complete successful artifact Instructions payload. */
|
|
348
|
+
const CliArtifactInstructionsSuccessSchema = z.object({
|
|
349
|
+
changeName: z.string(),
|
|
350
|
+
artifactId: z.string(),
|
|
351
|
+
schemaName: z.string(),
|
|
352
|
+
changeDir: z.string(),
|
|
353
|
+
planningHome: CliPlanningHomeSchema,
|
|
354
|
+
outputPath: z.string(),
|
|
355
|
+
resolvedOutputPath: z.string(),
|
|
356
|
+
existingOutputPaths: z.array(z.string()),
|
|
357
|
+
description: z.string(),
|
|
358
|
+
instruction: z.string().optional(),
|
|
359
|
+
context: z.string().optional(),
|
|
360
|
+
rules: z.array(z.string()).optional(),
|
|
361
|
+
template: z.string(),
|
|
362
|
+
dependencies: z.array(CliInstructionDependencySchema),
|
|
363
|
+
unlocks: z.array(z.string()),
|
|
364
|
+
references: z.array(CliReferenceIndexEntrySchema).optional(),
|
|
365
|
+
root: CliRootSchema
|
|
366
|
+
}).passthrough();
|
|
367
|
+
/** Typed success or diagnostic failure result for artifact Instructions. */
|
|
368
|
+
const CliArtifactInstructionsSchema = z.union([CliArtifactInstructionsSuccessSchema, CliDiagnosticFailureSchema]);
|
|
369
|
+
const CliApplyTaskSchema = z.object({
|
|
370
|
+
id: z.string(),
|
|
371
|
+
description: z.string(),
|
|
372
|
+
done: z.boolean()
|
|
373
|
+
}).passthrough();
|
|
374
|
+
/** Complete successful Apply Instructions payload, including raw Apply progress. */
|
|
375
|
+
const CliApplyInstructionsSuccessSchema = z.object({
|
|
376
|
+
changeName: z.string(),
|
|
377
|
+
changeDir: z.string(),
|
|
378
|
+
schemaName: z.string(),
|
|
379
|
+
contextFiles: z.record(z.array(z.string())),
|
|
380
|
+
progress: z.object({
|
|
381
|
+
total: z.number(),
|
|
382
|
+
complete: z.number(),
|
|
383
|
+
remaining: z.number()
|
|
384
|
+
}),
|
|
385
|
+
tasks: z.array(CliApplyTaskSchema),
|
|
386
|
+
state: z.enum([
|
|
387
|
+
"blocked",
|
|
388
|
+
"all_done",
|
|
389
|
+
"ready"
|
|
390
|
+
]),
|
|
391
|
+
missingArtifacts: z.array(z.string()).optional(),
|
|
392
|
+
instruction: z.string(),
|
|
393
|
+
references: z.array(CliReferenceIndexEntrySchema).optional(),
|
|
394
|
+
root: CliRootSchema
|
|
395
|
+
}).passthrough();
|
|
396
|
+
/** Typed success or diagnostic failure result of the CLI Apply Instructions command. */
|
|
397
|
+
const CliApplyInstructionsSchema = z.union([CliApplyInstructionsSuccessSchema, CliDiagnosticFailureSchema]);
|
|
398
|
+
const CliValidationIssueSchema = z.object({
|
|
399
|
+
level: z.enum([
|
|
400
|
+
"ERROR",
|
|
401
|
+
"WARNING",
|
|
402
|
+
"INFO"
|
|
403
|
+
]),
|
|
404
|
+
path: z.string(),
|
|
405
|
+
message: z.string(),
|
|
406
|
+
line: z.number().optional(),
|
|
407
|
+
column: z.number().optional()
|
|
408
|
+
}).passthrough();
|
|
409
|
+
const CliValidationTotalsSchema = z.object({
|
|
410
|
+
items: z.number(),
|
|
411
|
+
passed: z.number(),
|
|
412
|
+
failed: z.number()
|
|
413
|
+
}).passthrough();
|
|
414
|
+
/** Typed strict or non-strict Validate result, including upstream failure diagnostics. */
|
|
415
|
+
const CliValidateSchema = z.union([z.object({
|
|
416
|
+
items: z.array(z.object({
|
|
417
|
+
id: z.string(),
|
|
418
|
+
type: z.enum(["change", "spec"]),
|
|
419
|
+
valid: z.boolean(),
|
|
420
|
+
issues: z.array(CliValidationIssueSchema),
|
|
421
|
+
durationMs: z.number()
|
|
422
|
+
}).passthrough()),
|
|
423
|
+
summary: z.object({
|
|
424
|
+
totals: CliValidationTotalsSchema,
|
|
425
|
+
byType: z.record(CliValidationTotalsSchema)
|
|
426
|
+
}).passthrough(),
|
|
427
|
+
version: z.string(),
|
|
428
|
+
root: CliRootSchema
|
|
429
|
+
}).passthrough(), CliDiagnosticFailureSchema]);
|
|
430
|
+
const CliArchiveTotalsSchema = z.object({
|
|
431
|
+
added: z.number(),
|
|
432
|
+
modified: z.number(),
|
|
433
|
+
removed: z.number(),
|
|
434
|
+
renamed: z.number()
|
|
435
|
+
}).passthrough();
|
|
436
|
+
/** Typed Archive result without inferred retry or readiness semantics. */
|
|
437
|
+
const CliArchiveSchema = z.object({
|
|
438
|
+
archive: z.object({
|
|
439
|
+
change: z.string(),
|
|
440
|
+
archivedAs: z.string(),
|
|
441
|
+
path: z.string(),
|
|
442
|
+
specsUpdated: z.boolean(),
|
|
443
|
+
totals: CliArchiveTotalsSchema.optional()
|
|
444
|
+
}).passthrough().nullable(),
|
|
445
|
+
root: CliRootSchema.optional(),
|
|
446
|
+
status: z.array(CliDiagnosticSchema).optional()
|
|
447
|
+
}).passthrough();
|
|
448
|
+
|
|
449
|
+
//#endregion
|
|
450
|
+
//#region src/cli-contracts/executor.ts
|
|
451
|
+
/** Typed OpenSpec 1.6 command facade over the raw process executor. */
|
|
452
|
+
var OpenSpecCliContractExecutor = class {
|
|
453
|
+
constructor(executeCli) {
|
|
454
|
+
this.executeCli = executeCli;
|
|
455
|
+
}
|
|
456
|
+
async execute(args, schema) {
|
|
457
|
+
return parseCliCommandResult(await this.executeCli(args), schema);
|
|
458
|
+
}
|
|
459
|
+
withRoot(args, selector = {}) {
|
|
460
|
+
if (selector.store !== void 0) args.push("--store", selector.store);
|
|
461
|
+
return args;
|
|
462
|
+
}
|
|
463
|
+
withWorkflowOptions(args, options = {}) {
|
|
464
|
+
if (options.schema !== void 0) args.push("--schema", options.schema);
|
|
465
|
+
return this.withRoot(args, options);
|
|
466
|
+
}
|
|
467
|
+
/** List changes in the CLI-selected planning root. */
|
|
468
|
+
async listChanges(selector = {}) {
|
|
469
|
+
return this.execute(this.withRoot(["list", "--json"], selector), CliChangeListSchema);
|
|
470
|
+
}
|
|
471
|
+
/** List owned or explicitly selected Store Specs through the official CLI. */
|
|
472
|
+
async listSpecs(selector = {}) {
|
|
473
|
+
return this.execute(this.withRoot([
|
|
474
|
+
"list",
|
|
475
|
+
"--specs",
|
|
476
|
+
"--json"
|
|
477
|
+
], selector), CliSpecListSchema);
|
|
478
|
+
}
|
|
479
|
+
/** Read one owned or explicitly selected Store Spec through the official CLI. */
|
|
480
|
+
async showSpec(specId, selector = {}) {
|
|
481
|
+
return this.execute(this.withRoot([
|
|
482
|
+
"show",
|
|
483
|
+
specId,
|
|
484
|
+
"--type",
|
|
485
|
+
"spec",
|
|
486
|
+
"--json"
|
|
487
|
+
], selector), CliShowSpecSchema);
|
|
488
|
+
}
|
|
489
|
+
/** List workflow schemas through the CLI JSON contract. */
|
|
490
|
+
async schemas() {
|
|
491
|
+
return this.execute(["schemas", "--json"], CliSchemasSchema);
|
|
492
|
+
}
|
|
493
|
+
/** Resolve one workflow schema through the CLI JSON contract. */
|
|
494
|
+
async schemaWhich(name) {
|
|
495
|
+
return this.execute([
|
|
496
|
+
"schema",
|
|
497
|
+
"which",
|
|
498
|
+
name,
|
|
499
|
+
"--json"
|
|
500
|
+
], CliSchemaWhichSchema);
|
|
501
|
+
}
|
|
502
|
+
/** List the resolved template index through the CLI JSON contract. */
|
|
503
|
+
async templates(schema) {
|
|
504
|
+
const args = ["templates", "--json"];
|
|
505
|
+
if (schema !== void 0) args.push("--schema", schema);
|
|
506
|
+
return this.execute(args, CliTemplatesSchema);
|
|
507
|
+
}
|
|
508
|
+
/** Read complete workflow Status evidence for one change. */
|
|
509
|
+
async workflowStatus(changeId, options = {}) {
|
|
510
|
+
return this.execute(this.withWorkflowOptions([
|
|
511
|
+
"status",
|
|
512
|
+
"--change",
|
|
513
|
+
changeId,
|
|
514
|
+
"--json"
|
|
515
|
+
], options), CliWorkflowStatusSchema);
|
|
516
|
+
}
|
|
517
|
+
/** Read complete Instructions evidence for one workflow artifact. */
|
|
518
|
+
async artifactInstructions(changeId, artifactId, options = {}) {
|
|
519
|
+
return this.execute(this.withWorkflowOptions([
|
|
520
|
+
"instructions",
|
|
521
|
+
artifactId,
|
|
522
|
+
"--change",
|
|
523
|
+
changeId,
|
|
524
|
+
"--json"
|
|
525
|
+
], options), CliArtifactInstructionsSchema);
|
|
526
|
+
}
|
|
527
|
+
/** Read complete Apply Instructions evidence for one change. */
|
|
528
|
+
async applyInstructions(changeId, options = {}) {
|
|
529
|
+
return this.execute(this.withWorkflowOptions([
|
|
530
|
+
"instructions",
|
|
531
|
+
"apply",
|
|
532
|
+
"--change",
|
|
533
|
+
changeId,
|
|
534
|
+
"--json"
|
|
535
|
+
], options), CliApplyInstructionsSchema);
|
|
536
|
+
}
|
|
537
|
+
/** Inspect selected-root, Store, and Reference health through CLI Doctor. */
|
|
538
|
+
async doctorRoot(selector = {}) {
|
|
539
|
+
return this.execute(this.withRoot(["doctor", "--json"], selector), CliDoctorSchema);
|
|
540
|
+
}
|
|
541
|
+
/** Read the selected root and its direct Reference relationships. */
|
|
542
|
+
async context(selector = {}) {
|
|
543
|
+
return this.execute(this.withRoot(["context", "--json"], selector), CliContextSchema);
|
|
544
|
+
}
|
|
545
|
+
/** List Stores registered in the effective OpenSpec runtime environment. */
|
|
546
|
+
async listStores() {
|
|
547
|
+
return this.execute([
|
|
548
|
+
"store",
|
|
549
|
+
"list",
|
|
550
|
+
"--json"
|
|
551
|
+
], CliStoreListSchema);
|
|
552
|
+
}
|
|
553
|
+
/** Inspect all Stores or one explicitly present Store id. */
|
|
554
|
+
async doctorStores(id) {
|
|
555
|
+
const args = ["store", "doctor"];
|
|
556
|
+
if (id !== void 0) args.push(id);
|
|
557
|
+
args.push("--json");
|
|
558
|
+
return this.execute(args, CliStoreDoctorSchema);
|
|
559
|
+
}
|
|
560
|
+
/** Create and register a Store through the official CLI. */
|
|
561
|
+
async setupStore(id, options) {
|
|
562
|
+
const args = [
|
|
563
|
+
"store",
|
|
564
|
+
"setup",
|
|
565
|
+
id,
|
|
566
|
+
"--path",
|
|
567
|
+
options.path
|
|
568
|
+
];
|
|
569
|
+
if (options.initGit === true) args.push("--init-git");
|
|
570
|
+
if (options.initGit === false) args.push("--no-init-git");
|
|
571
|
+
if (options.remote !== void 0) args.push("--remote", options.remote);
|
|
572
|
+
args.push("--json");
|
|
573
|
+
return this.execute(args, CliStoreMutationSchema);
|
|
574
|
+
}
|
|
575
|
+
/** Register an existing Store root through the official CLI. */
|
|
576
|
+
async registerStore(path, options = {}) {
|
|
577
|
+
const args = [
|
|
578
|
+
"store",
|
|
579
|
+
"register",
|
|
580
|
+
path
|
|
581
|
+
];
|
|
582
|
+
if (options.id !== void 0) args.push("--id", options.id);
|
|
583
|
+
if (options.confirmIdentity) args.push("--yes");
|
|
584
|
+
args.push("--json");
|
|
585
|
+
return this.execute(args, CliStoreMutationSchema);
|
|
586
|
+
}
|
|
587
|
+
/** Remove one Store registry entry without deleting its checkout. */
|
|
588
|
+
async unregisterStore(id) {
|
|
589
|
+
return this.execute([
|
|
590
|
+
"store",
|
|
591
|
+
"unregister",
|
|
592
|
+
id,
|
|
593
|
+
"--json"
|
|
594
|
+
], CliStoreCleanupSchema);
|
|
595
|
+
}
|
|
596
|
+
/** Remove one Store through the official CLI destructive boundary. */
|
|
597
|
+
async removeStore(id, options = {}) {
|
|
598
|
+
const args = [
|
|
599
|
+
"store",
|
|
600
|
+
"remove",
|
|
601
|
+
id
|
|
602
|
+
];
|
|
603
|
+
if (options.confirmDelete) args.push("--yes");
|
|
604
|
+
args.push("--json");
|
|
605
|
+
return this.execute(args, CliStoreCleanupSchema);
|
|
606
|
+
}
|
|
607
|
+
/** Validate an item or scope without inferring retries or readiness. */
|
|
608
|
+
async validate(options) {
|
|
609
|
+
const args = ["validate"];
|
|
610
|
+
if (options.target.kind === "item") {
|
|
611
|
+
args.push(options.target.id);
|
|
612
|
+
if (options.target.type) args.push("--type", options.target.type);
|
|
613
|
+
} else args.push(`--${options.target.scope}`);
|
|
614
|
+
if (options.strict) args.push("--strict");
|
|
615
|
+
args.push("--json");
|
|
616
|
+
return this.execute(this.withRoot(args, options), CliValidateSchema);
|
|
617
|
+
}
|
|
618
|
+
/** Archive one change without implicit validation bypass or retry. */
|
|
619
|
+
async archive(changeId, options = {}) {
|
|
620
|
+
const args = [
|
|
621
|
+
"archive",
|
|
622
|
+
changeId,
|
|
623
|
+
"--json",
|
|
624
|
+
"--yes"
|
|
625
|
+
];
|
|
626
|
+
if (options.skipSpecs) args.push("--skip-specs");
|
|
627
|
+
if (options.noValidate) args.push("--no-validate");
|
|
628
|
+
return this.execute(this.withRoot(args, options), CliArchiveSchema);
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region src/spec-catalog.ts
|
|
634
|
+
/**
|
|
635
|
+
* Orthogonal intents (updated 2026-07-27 Asia/Shanghai):
|
|
636
|
+
* 1. Define collision-safe owned and referenced Spec identity.
|
|
637
|
+
* 2. Build one source-aware live/static Spec Catalog with CLI-owned membership and source-exact provenance.
|
|
638
|
+
* 3. Define source-distinct Spec detail projections without inventing upstream or snapshot fields.
|
|
639
|
+
* 4. Publish browser-safe Catalog/document runtime schemas for typed Projection Pull.
|
|
640
|
+
*
|
|
641
|
+
* Original request (2026-07-15): "Live and static modes share one source-aware Spec Catalog."
|
|
642
|
+
* Original request (2026-07-26): "展开全面的接口升级和内核升级和测试升级。"
|
|
643
|
+
*/
|
|
644
|
+
/** Runtime validator for one writable owned Spec identity. */
|
|
645
|
+
const OwnedSpecIdentitySchema = z.object({
|
|
646
|
+
kind: z.literal("owned"),
|
|
647
|
+
specId: z.string().min(1)
|
|
648
|
+
});
|
|
649
|
+
/** Runtime validator for one Store-qualified read-only Spec identity. */
|
|
650
|
+
const ReferencedSpecIdentitySchema = z.object({
|
|
651
|
+
kind: z.literal("referenced"),
|
|
652
|
+
storeId: z.string().min(1),
|
|
653
|
+
specId: z.string().min(1)
|
|
654
|
+
});
|
|
655
|
+
/** Runtime validator for the complete compound Spec identity union. */
|
|
656
|
+
const SpecIdentitySchema = z.discriminatedUnion("kind", [OwnedSpecIdentitySchema, ReferencedSpecIdentitySchema]);
|
|
657
|
+
const SpecCommandEvidenceSchema = CliProjectionCommandEvidenceSchema;
|
|
658
|
+
const OwnedSpecCatalogEntrySchema = z.object({
|
|
659
|
+
identity: OwnedSpecIdentitySchema,
|
|
660
|
+
source: z.literal("owned"),
|
|
661
|
+
readOnly: z.literal(false),
|
|
662
|
+
name: z.string(),
|
|
663
|
+
summary: z.null(),
|
|
664
|
+
requirementCount: z.number(),
|
|
665
|
+
updatedAt: z.number()
|
|
666
|
+
});
|
|
667
|
+
const SpecCatalogOwnedProjectionSchema = z.union([z.object({
|
|
668
|
+
provenance: z.literal("live"),
|
|
669
|
+
root: CliRootSchema,
|
|
670
|
+
evidence: SpecCommandEvidenceSchema
|
|
671
|
+
}), z.discriminatedUnion("state", [z.object({
|
|
672
|
+
provenance: z.literal("static"),
|
|
673
|
+
state: z.literal("available"),
|
|
674
|
+
snapshot: z.object({ specCount: z.number().int().nonnegative() })
|
|
675
|
+
}), z.object({
|
|
676
|
+
provenance: z.literal("static"),
|
|
677
|
+
state: z.literal("unavailable")
|
|
678
|
+
})])]);
|
|
679
|
+
const ReferencedSpecCatalogEntrySchema = z.object({
|
|
680
|
+
identity: ReferencedSpecIdentitySchema,
|
|
681
|
+
source: z.literal("referenced"),
|
|
682
|
+
readOnly: z.literal(true),
|
|
683
|
+
name: z.string(),
|
|
684
|
+
summary: z.null(),
|
|
685
|
+
requirementCount: z.number(),
|
|
686
|
+
updatedAt: z.literal(0)
|
|
687
|
+
});
|
|
688
|
+
const LiveSpecCatalogReferenceSourceSchema = z.object({
|
|
689
|
+
storeId: z.string(),
|
|
690
|
+
provenance: z.literal("live"),
|
|
691
|
+
state: z.enum(["ready", "error"]),
|
|
692
|
+
diagnostics: z.array(CliDiagnosticSchema),
|
|
693
|
+
evidence: SpecCommandEvidenceSchema
|
|
694
|
+
});
|
|
695
|
+
const StaticSpecCatalogReferenceSourceSchema = z.object({
|
|
696
|
+
storeId: z.string(),
|
|
697
|
+
provenance: z.literal("static"),
|
|
698
|
+
state: z.enum(["ready", "error"]),
|
|
699
|
+
snapshot: z.object({
|
|
700
|
+
policy: z.literal("include"),
|
|
701
|
+
specCount: z.number()
|
|
702
|
+
})
|
|
703
|
+
});
|
|
704
|
+
const SpecCatalogReferenceProjectionSchema = z.union([z.object({ provenance: z.literal("live") }), z.discriminatedUnion("policy", [
|
|
705
|
+
z.object({
|
|
706
|
+
provenance: z.literal("static"),
|
|
707
|
+
policy: z.literal("include")
|
|
708
|
+
}),
|
|
709
|
+
z.object({
|
|
710
|
+
provenance: z.literal("static"),
|
|
711
|
+
policy: z.literal("omit"),
|
|
712
|
+
referenceSourceCount: z.number()
|
|
713
|
+
}),
|
|
714
|
+
z.object({
|
|
715
|
+
provenance: z.literal("static"),
|
|
716
|
+
policy: z.literal("none")
|
|
717
|
+
}),
|
|
718
|
+
z.object({
|
|
719
|
+
provenance: z.literal("static"),
|
|
720
|
+
policy: z.literal("unavailable")
|
|
721
|
+
})
|
|
722
|
+
])]);
|
|
723
|
+
/** Runtime schema for the complete source-aware Spec Catalog. */
|
|
724
|
+
const SpecCatalogSchema = z.object({
|
|
725
|
+
entries: z.array(z.union([OwnedSpecCatalogEntrySchema, ReferencedSpecCatalogEntrySchema])),
|
|
726
|
+
ownedProjection: SpecCatalogOwnedProjectionSchema,
|
|
727
|
+
referenceSources: z.array(z.union([LiveSpecCatalogReferenceSourceSchema, StaticSpecCatalogReferenceSourceSchema])),
|
|
728
|
+
referenceProjection: SpecCatalogReferenceProjectionSchema,
|
|
729
|
+
observedAt: z.number()
|
|
730
|
+
});
|
|
731
|
+
/** Map a published snapshot count without implying that the browser executed OpenSpec CLI. */
|
|
732
|
+
function createStaticSpecCatalogOwnedProjection(specCount) {
|
|
733
|
+
return specCount === void 0 ? {
|
|
734
|
+
provenance: "static",
|
|
735
|
+
state: "unavailable"
|
|
736
|
+
} : {
|
|
737
|
+
provenance: "static",
|
|
738
|
+
state: "available",
|
|
739
|
+
snapshot: { specCount }
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
/** Map published Reference source facts without implying a CLI execution occurred. */
|
|
743
|
+
function createStaticSpecCatalogReferenceSource(input) {
|
|
744
|
+
return {
|
|
745
|
+
storeId: input.storeId,
|
|
746
|
+
provenance: "static",
|
|
747
|
+
state: input.state,
|
|
748
|
+
snapshot: {
|
|
749
|
+
policy: "include",
|
|
750
|
+
specCount: input.specCount
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
/** Map published static policy without converting omitted or unavailable facts into empty live inventory. */
|
|
755
|
+
function createStaticSpecCatalogReferenceProjection(policy) {
|
|
756
|
+
return match(policy).with(void 0, () => ({
|
|
757
|
+
provenance: "static",
|
|
758
|
+
policy: "unavailable"
|
|
759
|
+
})).with({ kind: "include" }, () => ({
|
|
760
|
+
provenance: "static",
|
|
761
|
+
policy: "include"
|
|
762
|
+
})).with({ kind: "omit" }, ({ referenceSourceCount }) => ({
|
|
763
|
+
provenance: "static",
|
|
764
|
+
policy: "omit",
|
|
765
|
+
referenceSourceCount
|
|
766
|
+
})).with({ kind: "none" }, () => ({
|
|
767
|
+
provenance: "static",
|
|
768
|
+
policy: "none"
|
|
769
|
+
})).exhaustive();
|
|
770
|
+
}
|
|
771
|
+
const OwnedSpecDocumentProjectionSchema = z.object({
|
|
772
|
+
identity: OwnedSpecIdentitySchema,
|
|
773
|
+
source: z.literal("owned"),
|
|
774
|
+
readOnly: z.literal(false),
|
|
775
|
+
state: z.enum(["ready", "not-found"]),
|
|
776
|
+
spec: SpecSchema.nullable(),
|
|
777
|
+
rawMarkdown: z.string().nullable(),
|
|
778
|
+
upstream: z.null(),
|
|
779
|
+
evidence: z.null()
|
|
780
|
+
});
|
|
781
|
+
const LiveReferencedSpecDocumentProjectionSchema = z.object({
|
|
782
|
+
identity: ReferencedSpecIdentitySchema,
|
|
783
|
+
source: z.literal("referenced"),
|
|
784
|
+
readOnly: z.literal(true),
|
|
785
|
+
state: z.enum(["ready", "error"]),
|
|
786
|
+
spec: z.null(),
|
|
787
|
+
rawMarkdown: z.null(),
|
|
788
|
+
upstream: CliShowSpecDocumentSchema.nullable(),
|
|
789
|
+
provenance: z.object({ kind: z.literal("live") }),
|
|
790
|
+
evidence: SpecCommandEvidenceSchema
|
|
791
|
+
});
|
|
792
|
+
const StaticReferencedSpecDocumentProjectionSchema = z.object({
|
|
793
|
+
identity: ReferencedSpecIdentitySchema,
|
|
794
|
+
source: z.literal("referenced"),
|
|
795
|
+
readOnly: z.literal(true),
|
|
796
|
+
state: z.enum(["ready", "error"]),
|
|
797
|
+
spec: SpecSchema.nullable(),
|
|
798
|
+
rawMarkdown: z.string().nullable(),
|
|
799
|
+
upstream: CliShowSpecDocumentSchema.nullable(),
|
|
800
|
+
provenance: z.discriminatedUnion("state", [
|
|
801
|
+
z.object({
|
|
802
|
+
kind: z.literal("static"),
|
|
803
|
+
state: z.enum(["included", "missing"]),
|
|
804
|
+
policy: z.enum(["include", "unrecorded"]),
|
|
805
|
+
source: StaticSpecCatalogReferenceSourceSchema.nullable()
|
|
806
|
+
}),
|
|
807
|
+
z.object({
|
|
808
|
+
kind: z.literal("static"),
|
|
809
|
+
state: z.literal("omitted"),
|
|
810
|
+
policy: z.literal("omit"),
|
|
811
|
+
referenceSourceCount: z.number()
|
|
812
|
+
}),
|
|
813
|
+
z.object({
|
|
814
|
+
kind: z.literal("static"),
|
|
815
|
+
state: z.literal("none"),
|
|
816
|
+
policy: z.literal("none")
|
|
817
|
+
}),
|
|
818
|
+
z.object({
|
|
819
|
+
kind: z.literal("static"),
|
|
820
|
+
state: z.literal("snapshot-unavailable"),
|
|
821
|
+
policy: z.literal("absent")
|
|
822
|
+
})
|
|
823
|
+
]),
|
|
824
|
+
evidence: z.null()
|
|
825
|
+
});
|
|
826
|
+
/** Runtime schema for one source-aware owned or referenced Spec document projection. */
|
|
827
|
+
const SpecDocumentProjectionSchema = z.union([
|
|
828
|
+
OwnedSpecDocumentProjectionSchema,
|
|
829
|
+
LiveReferencedSpecDocumentProjectionSchema,
|
|
830
|
+
StaticReferencedSpecDocumentProjectionSchema
|
|
831
|
+
]);
|
|
832
|
+
/** Build a collision-safe cache/search key for a compound Spec identity. */
|
|
833
|
+
function specIdentityKey(identity) {
|
|
834
|
+
const specId = encodeURIComponent(identity.specId);
|
|
835
|
+
return identity.kind === "owned" ? `owned:${specId}` : `referenced:${encodeURIComponent(identity.storeId)}:${specId}`;
|
|
836
|
+
}
|
|
837
|
+
/** Build the canonical live/static route for a compound Spec identity. */
|
|
838
|
+
function specRoutePath(identity) {
|
|
839
|
+
const specId = encodeURIComponent(identity.specId);
|
|
840
|
+
return identity.kind === "owned" ? `/specs/owned/${specId}` : `/specs/referenced/${encodeURIComponent(identity.storeId)}/${specId}`;
|
|
841
|
+
}
|
|
842
|
+
/** Recover compound Spec identity from canonical route parameters. */
|
|
843
|
+
function specIdentityFromRoute(params) {
|
|
844
|
+
return params.storeId === void 0 ? {
|
|
845
|
+
kind: "owned",
|
|
846
|
+
specId: params.specId
|
|
847
|
+
} : {
|
|
848
|
+
kind: "referenced",
|
|
849
|
+
storeId: params.storeId,
|
|
850
|
+
specId: params.specId
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
/** Merge already projected owned and referenced entries without bare-id deduplication. */
|
|
854
|
+
function mergeSpecCatalog(owned, referenced, ownedProjection, referenceSources, observedAt, referenceProjection = { provenance: "live" }) {
|
|
855
|
+
return {
|
|
856
|
+
entries: [...owned, ...referenced],
|
|
857
|
+
ownedProjection,
|
|
858
|
+
referenceSources: [...referenceSources],
|
|
859
|
+
referenceProjection,
|
|
860
|
+
observedAt
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
/** Project CLI-owned Spec membership and explicit per-Store Spec lists into one Catalog. */
|
|
864
|
+
function buildSpecCatalog(input) {
|
|
865
|
+
return mergeSpecCatalog(input.owned.map((spec) => ({
|
|
866
|
+
identity: {
|
|
867
|
+
kind: "owned",
|
|
868
|
+
specId: spec.id
|
|
869
|
+
},
|
|
870
|
+
source: "owned",
|
|
871
|
+
readOnly: false,
|
|
872
|
+
name: spec.id,
|
|
873
|
+
summary: null,
|
|
874
|
+
requirementCount: spec.requirementCount,
|
|
875
|
+
updatedAt: 0
|
|
876
|
+
})), input.referenced.flatMap((source) => source.specs.map((spec) => ({
|
|
877
|
+
identity: {
|
|
878
|
+
kind: "referenced",
|
|
879
|
+
storeId: source.storeId,
|
|
880
|
+
specId: spec.id
|
|
881
|
+
},
|
|
882
|
+
source: "referenced",
|
|
883
|
+
readOnly: true,
|
|
884
|
+
name: spec.id,
|
|
885
|
+
summary: null,
|
|
886
|
+
requirementCount: spec.requirementCount,
|
|
887
|
+
updatedAt: 0
|
|
888
|
+
}))), input.ownedProjection, input.referenceSources, input.observedAt);
|
|
889
|
+
}
|
|
890
|
+
/** Look up only the exact compound identity in a Catalog. */
|
|
891
|
+
function getSpecCatalogEntry(catalog, identity) {
|
|
892
|
+
const key = specIdentityKey(identity);
|
|
893
|
+
return catalog.entries.find((entry) => specIdentityKey(entry.identity) === key) ?? null;
|
|
894
|
+
}
|
|
895
|
+
/** Narrow a compound Spec identity to its Store-qualified read-only form. */
|
|
896
|
+
function isReferencedSpecIdentity(identity) {
|
|
897
|
+
return identity.kind === "referenced";
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
//#endregion
|
|
901
|
+
export { CliSchemasSchema as A, CliStoreCleanupSchema as B, CliArtifactInstructionsSuccessSchema as C, CliSchemaInfoSchema as D, CliPlanningHomeSchema as E, CliValidateSchema as F, CliStoreSchema as G, CliStoreDoctorSchema as H, CliWorkflowStatusSchema as I, parseCliCommandResult as K, CliWorkflowStatusSuccessSchema as L, CliShowSpecSchema as M, CliSpecListSchema as N, CliSchemaResolutionSchema as O, CliTemplateEntrySchema as P, CliContextSchema as R, CliArtifactInstructionsSchema as S, CliChangeListSchema as T, CliStoreListSchema as U, CliStoreDoctorEntrySchema as V, CliStoreMutationSchema as W, OpenSpecCliContractExecutor as _, SpecDocumentProjectionSchema as a, CliApplyInstructionsSuccessSchema as b, createStaticSpecCatalogOwnedProjection as c, getSpecCatalogEntry as d, isReferencedSpecIdentity as f, specRoutePath as g, specIdentityKey as h, SpecCommandEvidenceSchema as i, CliShowSpecDocumentSchema as j, CliSchemaShadowSchema as k, createStaticSpecCatalogReferenceProjection as l, specIdentityFromRoute as m, ReferencedSpecIdentitySchema as n, SpecIdentitySchema as o, mergeSpecCatalog as p, SpecCatalogSchema as r, buildSpecCatalog as s, OwnedSpecIdentitySchema as t, createStaticSpecCatalogReferenceSource as u, CliActionContextSchema as v, CliArtifactPathSchema as w, CliArchiveSchema as x, CliApplyInstructionsSchema as y, CliDoctorSchema as z };
|