@openspecui/web 11.0.0 → 12.0.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/assets/App-BagQkLCd.css +1 -0
- package/dist/assets/{App-DJc144W-.js → App-Dmag08k5.js} +108 -108
- package/dist/assets/{main-DXrIDd5i.js → main-DXjJbv3-.js} +2 -2
- package/dist/assets/{trpc-EqFJjKn0.js → trpc-CENMN-Kx.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-ssg/client/.vite/ssr-manifest.json +69 -29
- package/dist-ssg/client/assets/CanvasRenderer-B3YNEZKU.js +1 -0
- package/dist-ssg/client/assets/WebGLRenderer-91FdO4XE.js +1 -0
- package/dist-ssg/client/assets/WebGPURenderer-BcSREi3g.js +1 -0
- package/dist-ssg/client/assets/browserAll-CRvGxmXW.js +1 -0
- package/dist-ssg/client/assets/{config-guide-presentation-BcSY1KFl.js → config-guide-presentation-GtsojPuN.js} +1 -1
- package/dist-ssg/client/assets/{dist-DqLAJpLg.js → dist-B0xIEOgo.js} +1 -1
- package/dist-ssg/client/assets/{dist-B6Pffk4D.js → dist-BAP9yhhm.js} +1 -1
- package/dist-ssg/client/assets/dist-Bsojfco7.js +1 -0
- package/dist-ssg/client/assets/{dist-C24XzhQ9.js → dist-BxTQbErr.js} +1 -1
- package/dist-ssg/client/assets/{dist-C6Glwe3G.js → dist-C7lTRiju.js} +1 -1
- package/dist-ssg/client/assets/{dist-D_u4DgCb.js → dist-CI3zBObR.js} +1 -1
- package/dist-ssg/client/assets/{dist-WVAwgVsq.js → dist-CJOMMo-D.js} +1 -1
- package/dist-ssg/client/assets/{dist-iFk0rzRc.js → dist-Cgf7W726.js} +1 -1
- package/dist-ssg/client/assets/{dist--KYFoBcy.js → dist-DHkPjBBo.js} +1 -1
- package/dist-ssg/client/assets/{dist-DP2j-YyT.js → dist-Df3fSUJ8.js} +1 -1
- package/dist-ssg/client/assets/dist-fJz8f69P.js +1 -0
- package/dist-ssg/client/assets/dist-we8a11kz.js +1 -0
- package/dist-ssg/client/assets/{ghostty-web-lktg9S8z.js → ghostty-web-VZE4TZBO.js} +1 -1
- package/dist-ssg/client/assets/index-CS0xsSqt.css +1 -0
- package/dist-ssg/client/assets/index.ssg-m0qZ-Tbv.js +1650 -0
- package/dist-ssg/client/assets/{init-Cy2h-29G.js → init-0qJSx79q.js} +1 -1
- package/dist-ssg/client/assets/{trpc-DxTuySH7.js → trpc-D4bSp4J9.js} +1 -1
- package/dist-ssg/client/assets/webworkerAll-BUpVAcIt.js +1 -0
- package/dist-ssg/client/index.ssg.html +2 -2
- package/dist-ssg/server/assets/CanvasRenderer-eDcOd6Sl.js +3 -0
- package/dist-ssg/server/assets/WebGLRenderer-BYGgdFoJ.js +3 -0
- package/dist-ssg/server/assets/WebGPURenderer-CS5mt9ch.js +3 -0
- package/dist-ssg/server/assets/{browserAll-ByxW2BCo.js → browserAll-Da2y8ybl.js} +2 -2
- package/dist-ssg/server/assets/{config-guide-presentation-BfkVCRQq.js → config-guide-presentation-GWnVFKTW.js} +1 -1
- package/dist-ssg/server/assets/{dist-DvJqEVFD.js → dist-A6g9ScYS.js} +1 -1
- package/dist-ssg/server/assets/{dist-5xHpmSpA.js → dist-Bk9be2-W.js} +1 -1
- package/dist-ssg/server/assets/dist-C8ZGbZgL.js +3 -0
- package/dist-ssg/server/assets/{dist-DzYuWuV1.js → dist-C8mczL_o.js} +1 -1
- package/dist-ssg/server/assets/{dist-Cj2NABFW.js → dist-CRw-jyve.js} +1 -1
- package/dist-ssg/server/assets/{dist-wEaYViHh.js → dist-CmE7gK9r.js} +1 -1
- package/dist-ssg/server/assets/dist-D2ilXjzO.js +3 -0
- package/dist-ssg/server/assets/{dist-C-7lPLui.js → dist-D3Ubfaie.js} +1 -1
- package/dist-ssg/server/assets/{dist-j6yIDF4P.js → dist-DHhdkqG1.js} +1 -1
- package/dist-ssg/server/assets/dist-DbHDr3r9.js +3 -0
- package/dist-ssg/server/assets/{dist-7sF3GmjJ.js → dist-QLG95fVW.js} +1 -1
- package/dist-ssg/server/assets/{dist-BPIetWhy.js → dist-dHhPmrtl.js} +1 -1
- package/dist-ssg/server/assets/{entry-server-DccPywiF.js → entry-server-B1byBTHL.js} +963 -136
- package/dist-ssg/server/assets/{init-mk1myhk2.js → init-BCpyot27.js} +1 -1
- package/dist-ssg/server/assets/trpc-D5UIUAYV.js +3 -0
- package/dist-ssg/server/assets/webworkerAll-Dg825OUg.js +4 -0
- package/dist-ssg/server/ssr-entry-manifest.json +24 -24
- package/package.json +3 -3
- package/dist/assets/App-CRdki6ZH.css +0 -1
- package/dist-ssg/client/assets/CanvasRenderer-CngPuJLR.js +0 -1
- package/dist-ssg/client/assets/WebGLRenderer-D6PAqEKt.js +0 -1
- package/dist-ssg/client/assets/WebGPURenderer-CtCVeRwN.js +0 -1
- package/dist-ssg/client/assets/browserAll-BiLg81NS.js +0 -1
- package/dist-ssg/client/assets/dist-BN2GrXVl.js +0 -1
- package/dist-ssg/client/assets/dist-DqTWWRfT.js +0 -1
- package/dist-ssg/client/assets/dist-ZlYc7_kt.js +0 -1
- package/dist-ssg/client/assets/index-CDBo5TOs.css +0 -1
- package/dist-ssg/client/assets/index.ssg-n59gyR9q.js +0 -1650
- package/dist-ssg/client/assets/webworkerAll-B5n4bM-i.js +0 -1
- package/dist-ssg/server/assets/CanvasRenderer-D58O6peF.js +0 -3
- package/dist-ssg/server/assets/WebGLRenderer-CLVKAqNO.js +0 -3
- package/dist-ssg/server/assets/WebGPURenderer-D4vaKOO4.js +0 -3
- package/dist-ssg/server/assets/dist-CiijDa1h.js +0 -3
- package/dist-ssg/server/assets/dist-CkT7sc-T.js +0 -3
- package/dist-ssg/server/assets/dist-Ct3YhJiO.js +0 -3
- package/dist-ssg/server/assets/trpc-BPMx2lHD.js +0 -3
- package/dist-ssg/server/assets/webworkerAll-5v7Fs7LO.js +0 -4
|
@@ -30908,7 +30908,7 @@ var NavController = class {
|
|
|
30908
30908
|
this.storageKey = scopedStorageKey;
|
|
30909
30909
|
this.rebindProjectScopedLayout(scopedStorageKey);
|
|
30910
30910
|
}
|
|
30911
|
-
const { trpcClient } = await import("./trpc-
|
|
30911
|
+
const { trpcClient } = await import("./trpc-D5UIUAYV.js");
|
|
30912
30912
|
const remote = parsePersistedLayout(await trpcClient.kv.get.query({ key: this.storageKey }));
|
|
30913
30913
|
if (remote) {
|
|
30914
30914
|
if (remote.updatedAt > this.state.updatedAt) this.dispatch({
|
|
@@ -31051,7 +31051,7 @@ var NavController = class {
|
|
|
31051
31051
|
this.cancelPersistTimer();
|
|
31052
31052
|
this.persistTimer = setTimeout(() => {
|
|
31053
31053
|
this.persistTimer = null;
|
|
31054
|
-
import("./trpc-
|
|
31054
|
+
import("./trpc-D5UIUAYV.js").then(({ trpcClient }) => trpcClient.kv.set.mutate({
|
|
31055
31055
|
key: this.storageKey,
|
|
31056
31056
|
value: {
|
|
31057
31057
|
mainTabs: this.state.mainTabs,
|
|
@@ -39144,23 +39144,109 @@ var CliValidationTotalsSchema = objectType({
|
|
|
39144
39144
|
passed: numberType(),
|
|
39145
39145
|
failed: numberType()
|
|
39146
39146
|
}).passthrough();
|
|
39147
|
+
/** One bulk Validate item: verdict, full issue array, and runtime-dependent duration. */
|
|
39148
|
+
var CliValidateItemSchema = objectType({
|
|
39149
|
+
id: stringType(),
|
|
39150
|
+
type: enumType(["change", "spec"]),
|
|
39151
|
+
valid: booleanType(),
|
|
39152
|
+
issues: arrayType(CliValidationIssueSchema),
|
|
39153
|
+
durationMs: numberType()
|
|
39154
|
+
}).passthrough();
|
|
39155
|
+
/** Shared Validate summary: full-run totals plus per-type totals, never the filtered view. */
|
|
39156
|
+
var CliValidateSummarySchema = objectType({
|
|
39157
|
+
totals: CliValidationTotalsSchema,
|
|
39158
|
+
byType: recordType(CliValidationTotalsSchema)
|
|
39159
|
+
}).passthrough();
|
|
39147
39160
|
/** Typed ordinary Validate report, also used by 1.9 `validate --archived --json`. */
|
|
39148
39161
|
var CliValidateReportSchema = objectType({
|
|
39149
|
-
items: arrayType(
|
|
39150
|
-
|
|
39151
|
-
type: enumType(["change", "spec"]),
|
|
39152
|
-
valid: booleanType(),
|
|
39153
|
-
issues: arrayType(CliValidationIssueSchema),
|
|
39154
|
-
durationMs: numberType()
|
|
39155
|
-
}).passthrough()),
|
|
39156
|
-
summary: objectType({
|
|
39157
|
-
totals: CliValidationTotalsSchema,
|
|
39158
|
-
byType: recordType(CliValidationTotalsSchema)
|
|
39159
|
-
}).passthrough(),
|
|
39162
|
+
items: arrayType(CliValidateItemSchema),
|
|
39163
|
+
summary: CliValidateSummarySchema,
|
|
39160
39164
|
version: stringType(),
|
|
39161
39165
|
root: CliRootSchema
|
|
39162
39166
|
}).passthrough();
|
|
39163
39167
|
unionType([CliValidateReportSchema, CliDiagnosticFailureSchema]);
|
|
39168
|
+
/**
|
|
39169
|
+
* Typed OpenSpec 1.12 `validate --report findings` document.
|
|
39170
|
+
*
|
|
39171
|
+
* The findings report is a filtered evidence transport beside the full report, never the
|
|
39172
|
+
* validation truth: `itemFindings` carries only items with issues, while `summary` and
|
|
39173
|
+
* `root` stay the full-run values the CLI computed over every item in scope.
|
|
39174
|
+
* `report.returnedItems`/`report.totalItems` distinguish the filtered view from the run
|
|
39175
|
+
* size, and the process exit code keeps the full-run rule (`failed > 0 -> 1`), so decoding
|
|
39176
|
+
* never consults it. An empty scope is the success document
|
|
39177
|
+
* `{ returnedItems: 0, totalItems: 0, itemFindings: [] }`, not a failure sum type.
|
|
39178
|
+
*
|
|
39179
|
+
* Two upstream-guaranteed invariants are decode-level facts (pinned v1.12.0
|
|
39180
|
+
* `projectValidationFindings`): every `itemFindings` entry carries at least one issue
|
|
39181
|
+
* (upstream filters `item.issues.length > 0`), and `returnedItems` never exceeds
|
|
39182
|
+
* `totalItems` (the filtered view is a subset of the full run). Upstream also happens to
|
|
39183
|
+
* set `returnedItems === itemFindings.length` today; that equality stays unasserted so a
|
|
39184
|
+
* future patch-level count adjustment inside the admitted range cannot fabricate a
|
|
39185
|
+
* contract error out of otherwise well-formed CLI evidence.
|
|
39186
|
+
*/
|
|
39187
|
+
var CliValidateFindingsSchema = objectType({
|
|
39188
|
+
report: objectType({
|
|
39189
|
+
kind: literalType("validation-findings"),
|
|
39190
|
+
version: stringType(),
|
|
39191
|
+
scope: enumType([
|
|
39192
|
+
"all",
|
|
39193
|
+
"changes",
|
|
39194
|
+
"specs",
|
|
39195
|
+
"archived"
|
|
39196
|
+
]),
|
|
39197
|
+
returnedItems: numberType(),
|
|
39198
|
+
totalItems: numberType()
|
|
39199
|
+
}).passthrough(),
|
|
39200
|
+
itemFindings: arrayType(CliValidateItemSchema),
|
|
39201
|
+
summary: CliValidateSummarySchema,
|
|
39202
|
+
root: CliRootSchema
|
|
39203
|
+
}).passthrough().superRefine((document, ctx) => {
|
|
39204
|
+
if (document.report.returnedItems > document.report.totalItems) ctx.addIssue({
|
|
39205
|
+
code: ZodIssueCode.custom,
|
|
39206
|
+
path: ["report", "returnedItems"],
|
|
39207
|
+
message: `returnedItems (${document.report.returnedItems}) must not exceed totalItems (${document.report.totalItems}).`
|
|
39208
|
+
});
|
|
39209
|
+
document.itemFindings.forEach((finding, index) => {
|
|
39210
|
+
if (finding.issues.length === 0) ctx.addIssue({
|
|
39211
|
+
code: ZodIssueCode.custom,
|
|
39212
|
+
path: [
|
|
39213
|
+
"itemFindings",
|
|
39214
|
+
index,
|
|
39215
|
+
"issues"
|
|
39216
|
+
],
|
|
39217
|
+
message: "Every findings item must carry at least one issue."
|
|
39218
|
+
});
|
|
39219
|
+
});
|
|
39220
|
+
});
|
|
39221
|
+
/**
|
|
39222
|
+
* Typed findings or request-failure result of `validate --report findings --json`.
|
|
39223
|
+
*
|
|
39224
|
+
* Invalid requests (no bulk scope, an item name, archived+active mixing, or an unknown
|
|
39225
|
+
* report value) produce the shared status-array failure envelope with code
|
|
39226
|
+
* `invalid_validation_report_request`, decoded here through the shared diagnostic
|
|
39227
|
+
* failure schema including its optional `fix` string.
|
|
39228
|
+
*/
|
|
39229
|
+
var CliValidateFindingsResultSchema = unionType([CliValidateFindingsSchema, CliDiagnosticFailureSchema]);
|
|
39230
|
+
/**
|
|
39231
|
+
* Whether a findings result is the findings document rather than the request-failure
|
|
39232
|
+
* envelope. Passthrough tolerance means a failure envelope may legally carry unknown
|
|
39233
|
+
* keys, so mere `report`-key presence cannot discriminate the union: the guard validates
|
|
39234
|
+
* the upstream discriminator shape — `report` is an object whose `kind` is the
|
|
39235
|
+
* `validation-findings` literal and whose count fields are numbers.
|
|
39236
|
+
*
|
|
39237
|
+
* The input is deliberately `unknown`: route and evidence consumers receive the union
|
|
39238
|
+
* of every validate transport (`CliValidate | CliValidateFindingsResult | null`), so the
|
|
39239
|
+
* guard must accept the consumed boundary, not only the already-narrowed findings union.
|
|
39240
|
+
* It stays a cheap shape check, never a second decode: schema-level invariants
|
|
39241
|
+
* (issue presence, count bounds) belong to `CliValidateFindingsSchema` alone.
|
|
39242
|
+
*/
|
|
39243
|
+
function isCliValidateFindings(result) {
|
|
39244
|
+
if (typeof result !== "object" || result === null) return false;
|
|
39245
|
+
const report = result.report;
|
|
39246
|
+
if (typeof report !== "object" || report === null) return false;
|
|
39247
|
+
const { kind, returnedItems, totalItems } = report;
|
|
39248
|
+
return kind === "validation-findings" && typeof returnedItems === "number" && typeof totalItems === "number";
|
|
39249
|
+
}
|
|
39164
39250
|
var CliArchiveTotalsSchema = objectType({
|
|
39165
39251
|
added: numberType(),
|
|
39166
39252
|
modified: numberType(),
|
|
@@ -47051,6 +47137,20 @@ var Moon = createLucideIcon("Moon", [["path", {
|
|
|
47051
47137
|
d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z",
|
|
47052
47138
|
key: "a7tn18"
|
|
47053
47139
|
}]]);
|
|
47140
|
+
var OctagonAlert = createLucideIcon("OctagonAlert", [
|
|
47141
|
+
["path", {
|
|
47142
|
+
d: "M12 16h.01",
|
|
47143
|
+
key: "1drbdi"
|
|
47144
|
+
}],
|
|
47145
|
+
["path", {
|
|
47146
|
+
d: "M12 8v4",
|
|
47147
|
+
key: "1got3b"
|
|
47148
|
+
}],
|
|
47149
|
+
["path", {
|
|
47150
|
+
d: "M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z",
|
|
47151
|
+
key: "1fd625"
|
|
47152
|
+
}]
|
|
47153
|
+
]);
|
|
47054
47154
|
var PackageOpen = createLucideIcon("PackageOpen", [
|
|
47055
47155
|
["path", {
|
|
47056
47156
|
d: "M12 22v-9",
|
|
@@ -71180,7 +71280,7 @@ var browserExt = {
|
|
|
71180
71280
|
},
|
|
71181
71281
|
test: () => true,
|
|
71182
71282
|
load: async () => {
|
|
71183
|
-
await import("./browserAll-
|
|
71283
|
+
await import("./browserAll-Da2y8ybl.js");
|
|
71184
71284
|
}
|
|
71185
71285
|
};
|
|
71186
71286
|
//#endregion
|
|
@@ -71193,7 +71293,7 @@ var webworkerExt = {
|
|
|
71193
71293
|
},
|
|
71194
71294
|
test: () => typeof self !== "undefined" && self.WorkerGlobalScope !== void 0,
|
|
71195
71295
|
load: async () => {
|
|
71196
|
-
await import("./webworkerAll-
|
|
71296
|
+
await import("./webworkerAll-Dg825OUg.js");
|
|
71197
71297
|
}
|
|
71198
71298
|
};
|
|
71199
71299
|
//#endregion
|
|
@@ -73787,7 +73887,7 @@ async function autoDetectRenderer(options) {
|
|
|
73787
73887
|
for (let i = 0; i < preferredOrder.length; i++) {
|
|
73788
73888
|
const rendererType = preferredOrder[i];
|
|
73789
73889
|
if (rendererType === "webgpu" && await isWebGPUSupported()) {
|
|
73790
|
-
const { WebGPURenderer } = await import("./WebGPURenderer-
|
|
73890
|
+
const { WebGPURenderer } = await import("./WebGPURenderer-CS5mt9ch.js");
|
|
73791
73891
|
RendererClass = WebGPURenderer;
|
|
73792
73892
|
finalOptions = {
|
|
73793
73893
|
...options,
|
|
@@ -73795,7 +73895,7 @@ async function autoDetectRenderer(options) {
|
|
|
73795
73895
|
};
|
|
73796
73896
|
break;
|
|
73797
73897
|
} else if (rendererType === "webgl" && isWebGLSupported(options.failIfMajorPerformanceCaveat ?? AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat)) {
|
|
73798
|
-
const { WebGLRenderer } = await import("./WebGLRenderer-
|
|
73898
|
+
const { WebGLRenderer } = await import("./WebGLRenderer-BYGgdFoJ.js");
|
|
73799
73899
|
RendererClass = WebGLRenderer;
|
|
73800
73900
|
finalOptions = {
|
|
73801
73901
|
...options,
|
|
@@ -73803,7 +73903,7 @@ async function autoDetectRenderer(options) {
|
|
|
73803
73903
|
};
|
|
73804
73904
|
break;
|
|
73805
73905
|
} else if (rendererType === "canvas") {
|
|
73806
|
-
const { CanvasRenderer } = await import("./CanvasRenderer-
|
|
73906
|
+
const { CanvasRenderer } = await import("./CanvasRenderer-eDcOd6Sl.js");
|
|
73807
73907
|
RendererClass = CanvasRenderer;
|
|
73808
73908
|
finalOptions = {
|
|
73809
73909
|
...options,
|
|
@@ -97552,7 +97652,7 @@ var TerminalController = class {
|
|
|
97552
97652
|
if (this.configPersistTimer) clearTimeout(this.configPersistTimer);
|
|
97553
97653
|
this.configPersistTimer = setTimeout(() => {
|
|
97554
97654
|
this.configPersistTimer = null;
|
|
97555
|
-
import("./trpc-
|
|
97655
|
+
import("./trpc-D5UIUAYV.js").then(({ trpcClient }) => {
|
|
97556
97656
|
trpcClient.config.update.mutate({ terminal: { fontSize: this.config.fontSize } });
|
|
97557
97657
|
}).catch(() => {});
|
|
97558
97658
|
}, CONFIG_PERSIST_DEBOUNCE);
|
|
@@ -108113,7 +108213,7 @@ var languages = [
|
|
|
108113
108213
|
name: "CSS",
|
|
108114
108214
|
extensions: ["css"],
|
|
108115
108215
|
load() {
|
|
108116
|
-
return import("./dist-
|
|
108216
|
+
return import("./dist-C8ZGbZgL.js").then((m) => m.css());
|
|
108117
108217
|
}
|
|
108118
108218
|
}),
|
|
108119
108219
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108133,7 +108233,7 @@ var languages = [
|
|
|
108133
108233
|
"hbs"
|
|
108134
108234
|
],
|
|
108135
108235
|
load() {
|
|
108136
|
-
return import("./dist-
|
|
108236
|
+
return import("./dist-dHhPmrtl.js").then((m) => m.html());
|
|
108137
108237
|
}
|
|
108138
108238
|
}),
|
|
108139
108239
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108167,7 +108267,7 @@ var languages = [
|
|
|
108167
108267
|
"jinja2"
|
|
108168
108268
|
],
|
|
108169
108269
|
load() {
|
|
108170
|
-
return import("./dist-
|
|
108270
|
+
return import("./dist-CRw-jyve.js").then((m) => m.jinja());
|
|
108171
108271
|
}
|
|
108172
108272
|
}),
|
|
108173
108273
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108175,7 +108275,7 @@ var languages = [
|
|
|
108175
108275
|
alias: ["json5"],
|
|
108176
108276
|
extensions: ["json", "map"],
|
|
108177
108277
|
load() {
|
|
108178
|
-
return import("./dist-
|
|
108278
|
+
return import("./dist-D2ilXjzO.js").then((m) => m.json());
|
|
108179
108279
|
}
|
|
108180
108280
|
}),
|
|
108181
108281
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108189,14 +108289,14 @@ var languages = [
|
|
|
108189
108289
|
name: "LESS",
|
|
108190
108290
|
extensions: ["less"],
|
|
108191
108291
|
load() {
|
|
108192
|
-
return import("./dist-
|
|
108292
|
+
return import("./dist-C8mczL_o.js").then((m) => m.less());
|
|
108193
108293
|
}
|
|
108194
108294
|
}),
|
|
108195
108295
|
/* @__PURE__ */ LanguageDescription.of({
|
|
108196
108296
|
name: "Liquid",
|
|
108197
108297
|
extensions: ["liquid"],
|
|
108198
108298
|
load() {
|
|
108199
|
-
return import("./dist-
|
|
108299
|
+
return import("./dist-CmE7gK9r.js").then((m) => m.liquid());
|
|
108200
108300
|
}
|
|
108201
108301
|
}),
|
|
108202
108302
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108213,7 +108313,7 @@ var languages = [
|
|
|
108213
108313
|
"mkd"
|
|
108214
108314
|
],
|
|
108215
108315
|
load() {
|
|
108216
|
-
return import("./dist-
|
|
108316
|
+
return import("./dist-Bk9be2-W.js").then((m) => m.markdown());
|
|
108217
108317
|
}
|
|
108218
108318
|
}),
|
|
108219
108319
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108239,7 +108339,7 @@ var languages = [
|
|
|
108239
108339
|
"phtml"
|
|
108240
108340
|
],
|
|
108241
108341
|
load() {
|
|
108242
|
-
return import("./dist-
|
|
108342
|
+
return import("./dist-QLG95fVW.js").then((m) => m.php());
|
|
108243
108343
|
}
|
|
108244
108344
|
}),
|
|
108245
108345
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108279,14 +108379,14 @@ var languages = [
|
|
|
108279
108379
|
name: "Sass",
|
|
108280
108380
|
extensions: ["sass"],
|
|
108281
108381
|
load() {
|
|
108282
|
-
return import("./dist-
|
|
108382
|
+
return import("./dist-D3Ubfaie.js").then((m) => m.sass({ indented: true }));
|
|
108283
108383
|
}
|
|
108284
108384
|
}),
|
|
108285
108385
|
/* @__PURE__ */ LanguageDescription.of({
|
|
108286
108386
|
name: "SCSS",
|
|
108287
108387
|
extensions: ["scss"],
|
|
108288
108388
|
load() {
|
|
108289
|
-
return import("./dist-
|
|
108389
|
+
return import("./dist-D3Ubfaie.js").then((m) => m.sass());
|
|
108290
108390
|
}
|
|
108291
108391
|
}),
|
|
108292
108392
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -108353,7 +108453,7 @@ var languages = [
|
|
|
108353
108453
|
alias: ["yml"],
|
|
108354
108454
|
extensions: ["yaml", "yml"],
|
|
108355
108455
|
load() {
|
|
108356
|
-
return import("./dist-
|
|
108456
|
+
return import("./dist-DbHDr3r9.js").then((m) => m.yaml());
|
|
108357
108457
|
}
|
|
108358
108458
|
}),
|
|
108359
108459
|
/* @__PURE__ */ LanguageDescription.of({
|
|
@@ -109240,13 +109340,13 @@ var languages = [
|
|
|
109240
109340
|
name: "Vue",
|
|
109241
109341
|
extensions: ["vue"],
|
|
109242
109342
|
load() {
|
|
109243
|
-
return import("./dist-
|
|
109343
|
+
return import("./dist-A6g9ScYS.js").then((m) => m.vue());
|
|
109244
109344
|
}
|
|
109245
109345
|
}),
|
|
109246
109346
|
/* @__PURE__ */ LanguageDescription.of({
|
|
109247
109347
|
name: "Angular Template",
|
|
109248
109348
|
load() {
|
|
109249
|
-
return import("./dist-
|
|
109349
|
+
return import("./dist-DHhdkqG1.js").then((m) => m.angular());
|
|
109250
109350
|
}
|
|
109251
109351
|
})
|
|
109252
109352
|
];
|
|
@@ -171483,17 +171583,31 @@ function ChangeReferenceFailureNotice({ referenceEvidence }) {
|
|
|
171483
171583
|
});
|
|
171484
171584
|
}
|
|
171485
171585
|
//#endregion
|
|
171586
|
+
//#region src/components/evidence-layer-header.tsx
|
|
171587
|
+
function EvidenceLayerHeader({ title, summary }) {
|
|
171588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
|
|
171589
|
+
className: "border-border mb-4 flex min-w-0 flex-wrap items-baseline justify-between gap-x-3 gap-y-1 border-b py-2.5",
|
|
171590
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
|
|
171591
|
+
className: "min-w-0 text-sm font-semibold tracking-tight",
|
|
171592
|
+
children: title
|
|
171593
|
+
}), summary ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
171594
|
+
className: "text-muted-foreground min-w-0 text-[11px]",
|
|
171595
|
+
children: summary
|
|
171596
|
+
}) : null]
|
|
171597
|
+
});
|
|
171598
|
+
}
|
|
171599
|
+
//#endregion
|
|
171486
171600
|
//#region ../core/src/openspec-compat.ts
|
|
171487
|
-
var OPENSPEC_CLI_TARGET_SERIES = "1.
|
|
171488
|
-
var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.
|
|
171489
|
-
var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.
|
|
171601
|
+
var OPENSPEC_CLI_TARGET_SERIES = "1.12";
|
|
171602
|
+
var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.12"];
|
|
171603
|
+
var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.12.0 <1.13.0";
|
|
171490
171604
|
/**
|
|
171491
171605
|
* Derive command capabilities from one parsed CLI version.
|
|
171492
171606
|
*
|
|
171493
171607
|
* Only an admitted version — stable inside the accepted range — can select version-specific
|
|
171494
|
-
* capabilities. Unsupported forms (prereleases, >=1.
|
|
171608
|
+
* capabilities. Unsupported forms (prereleases, >=1.13, below-range) and unparseable output
|
|
171495
171609
|
* keep their mismatch evidence and expose no capability, so a page-level version bypass can
|
|
171496
|
-
* never manufacture a 1.
|
|
171610
|
+
* never manufacture a 1.12 command surface for a CLI the release line does not admit.
|
|
171497
171611
|
*/
|
|
171498
171612
|
function deriveOpenSpecCliCapabilities(version) {
|
|
171499
171613
|
if (!isAdmittedVersion(version)) return {
|
|
@@ -171501,7 +171615,8 @@ function deriveOpenSpecCliCapabilities(version) {
|
|
|
171501
171615
|
archivedValidation: false,
|
|
171502
171616
|
initLanguage: false,
|
|
171503
171617
|
batchStatus: false,
|
|
171504
|
-
requirementDiff: false
|
|
171618
|
+
requirementDiff: false,
|
|
171619
|
+
findingsReport: false
|
|
171505
171620
|
};
|
|
171506
171621
|
const onTargetSeries = isSeries(version, OPENSPEC_CLI_TARGET_SERIES);
|
|
171507
171622
|
return {
|
|
@@ -171509,7 +171624,8 @@ function deriveOpenSpecCliCapabilities(version) {
|
|
|
171509
171624
|
archivedValidation: true,
|
|
171510
171625
|
initLanguage: true,
|
|
171511
171626
|
batchStatus: onTargetSeries,
|
|
171512
|
-
requirementDiff: onTargetSeries
|
|
171627
|
+
requirementDiff: onTargetSeries,
|
|
171628
|
+
findingsReport: onTargetSeries
|
|
171513
171629
|
};
|
|
171514
171630
|
}
|
|
171515
171631
|
function parseOpenSpecCliVersion(raw) {
|
|
@@ -171533,7 +171649,7 @@ function isStable(version) {
|
|
|
171533
171649
|
/** True only for stable versions inside the accepted range (current or supported non-current). */
|
|
171534
171650
|
function isAdmittedVersion(version) {
|
|
171535
171651
|
if (!version || !isStable(version)) return false;
|
|
171536
|
-
return isSeries(version, "1.
|
|
171652
|
+
return isSeries(version, "1.12") || isSupportedNonCurrentSeries(version);
|
|
171537
171653
|
}
|
|
171538
171654
|
function isSupportedNonCurrentSeries(version) {
|
|
171539
171655
|
return OPENSPEC_CLI_SUPPORTED_SERIES.filter((series) => series !== OPENSPEC_CLI_TARGET_SERIES).some((series) => isSeries(version, series));
|
|
@@ -171541,12 +171657,12 @@ function isSupportedNonCurrentSeries(version) {
|
|
|
171541
171657
|
//#endregion
|
|
171542
171658
|
//#region src/components/archived-validation-evidence.tsx
|
|
171543
171659
|
/**
|
|
171544
|
-
* Orthogonal intents (updated 2026-
|
|
171660
|
+
* Orthogonal intents (updated 2026-09-03 Asia/Shanghai):
|
|
171545
171661
|
* 1. Present OpenSpec `validate --archived --json` as typed CLI evidence.
|
|
171546
171662
|
* 2. Preserve item issues, totals, root, and exit/failure evidence without repair actions.
|
|
171547
171663
|
* 3. Identify the evidence as unavailable in static snapshots instead of fabricating it.
|
|
171548
|
-
* 4. Derive the capability from the detected admitted CLI;
|
|
171549
|
-
*
|
|
171664
|
+
* 4. Derive the capability from the detected admitted CLI; the admitted 1.12 line declares
|
|
171665
|
+
* it, so the unavailable branch names the accepted range, not one series.
|
|
171550
171666
|
* 5. Validate report payloads with the Core contract schema, never shallow shape guards.
|
|
171551
171667
|
* 6. Mount directly inside the Evidence workspace detail pane: the Accordion shell is gone, the
|
|
171552
171668
|
* section header keeps the title and summary facts, and `onChip` reports only derived facts
|
|
@@ -171555,8 +171671,10 @@ function isSupportedNonCurrentSeries(version) {
|
|
|
171555
171671
|
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
171556
171672
|
* Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
|
|
171557
171673
|
* Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
|
|
171674
|
+
* Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
|
|
171675
|
+
* Owner walkthrough correction (2026-09-04): every Evidence detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding); this replaces each layer's local weak header.
|
|
171558
171676
|
*/
|
|
171559
|
-
function parseValidationReport(value) {
|
|
171677
|
+
function parseValidationReport$1(value) {
|
|
171560
171678
|
const parsed = CliValidateReportSchema.safeParse(value);
|
|
171561
171679
|
if (parsed.success) return {
|
|
171562
171680
|
report: parsed.data,
|
|
@@ -171567,7 +171685,7 @@ function parseValidationReport(value) {
|
|
|
171567
171685
|
schemaIssues: parsed.error.issues.map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`)
|
|
171568
171686
|
};
|
|
171569
171687
|
}
|
|
171570
|
-
function IssueList({ issues }) {
|
|
171688
|
+
function IssueList$1({ issues }) {
|
|
171571
171689
|
if (issues.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
171572
171690
|
className: "text-muted-foreground",
|
|
171573
171691
|
children: "No CLI issue reported."
|
|
@@ -171586,7 +171704,7 @@ function IssueList({ issues }) {
|
|
|
171586
171704
|
}, index))
|
|
171587
171705
|
});
|
|
171588
171706
|
}
|
|
171589
|
-
function RunButton({ pending, label, onRun }) {
|
|
171707
|
+
function RunButton$2({ pending, label, onRun }) {
|
|
171590
171708
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
171591
171709
|
type: "button",
|
|
171592
171710
|
onClick: onRun,
|
|
@@ -171612,17 +171730,11 @@ function ArchivedValidationSection({ summary, children }) {
|
|
|
171612
171730
|
"data-evidence-section": "archived-validation",
|
|
171613
171731
|
"aria-label": "Archived validation",
|
|
171614
171732
|
className: "min-w-0",
|
|
171615
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
171616
|
-
|
|
171617
|
-
|
|
171618
|
-
className: "min-w-0 text-xs font-semibold",
|
|
171619
|
-
children: "Archived validation"
|
|
171620
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
171621
|
-
className: "text-muted-foreground min-w-0 text-[11px]",
|
|
171622
|
-
children: summary
|
|
171623
|
-
})]
|
|
171733
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceLayerHeader, {
|
|
171734
|
+
title: "Archived validation",
|
|
171735
|
+
summary
|
|
171624
171736
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
171625
|
-
className: "min-w-0
|
|
171737
|
+
className: "min-w-0 text-xs",
|
|
171626
171738
|
children
|
|
171627
171739
|
})]
|
|
171628
171740
|
});
|
|
@@ -171645,7 +171757,7 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171645
171757
|
tone: "unavailable"
|
|
171646
171758
|
};
|
|
171647
171759
|
if (!report && !error) return null;
|
|
171648
|
-
const parsed = report ? parseValidationReport(report.data) : {
|
|
171760
|
+
const parsed = report ? parseValidationReport$1(report.data) : {
|
|
171649
171761
|
report: null,
|
|
171650
171762
|
schemaIssues: []
|
|
171651
171763
|
};
|
|
@@ -171716,14 +171828,14 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171716
171828
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
171717
171829
|
className: "text-muted-foreground",
|
|
171718
171830
|
children: "Run the official CLI's archived-task validation and keep its typed report as evidence. OpenSpecUI never repairs or archives from here."
|
|
171719
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
171831
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$2, {
|
|
171720
171832
|
pending,
|
|
171721
171833
|
label: "Validate archived tasks",
|
|
171722
171834
|
onRun: () => void run()
|
|
171723
171835
|
})]
|
|
171724
171836
|
})
|
|
171725
171837
|
});
|
|
171726
|
-
const parsed = report ? parseValidationReport(report.data) : {
|
|
171838
|
+
const parsed = report ? parseValidationReport$1(report.data) : {
|
|
171727
171839
|
report: null,
|
|
171728
171840
|
schemaIssues: []
|
|
171729
171841
|
};
|
|
@@ -171744,7 +171856,7 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171744
171856
|
className: "min-w-0 break-all",
|
|
171745
171857
|
children: error ?? report?.contractError ?? schemaDiagnostic ?? report?.stderr.trim() ?? "The archived validation command failed."
|
|
171746
171858
|
})]
|
|
171747
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
171859
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$2, {
|
|
171748
171860
|
pending,
|
|
171749
171861
|
label: "Rerun",
|
|
171750
171862
|
onRun: () => void run()
|
|
@@ -171808,11 +171920,11 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171808
171920
|
})]
|
|
171809
171921
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
171810
171922
|
className: "mt-1",
|
|
171811
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IssueList, { issues: item.issues })
|
|
171923
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IssueList$1, { issues: item.issues })
|
|
171812
171924
|
})]
|
|
171813
171925
|
}, item.id))
|
|
171814
171926
|
}),
|
|
171815
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
171927
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$2, {
|
|
171816
171928
|
pending,
|
|
171817
171929
|
label: "Rerun",
|
|
171818
171930
|
onRun: () => void run()
|
|
@@ -171824,12 +171936,13 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171824
171936
|
//#endregion
|
|
171825
171937
|
//#region src/components/change-diff-evidence.tsx
|
|
171826
171938
|
/**
|
|
171827
|
-
* Orthogonal intents (updated 2026-
|
|
171939
|
+
* Orthogonal intents (updated 2026-09-03 Asia/Shanghai):
|
|
171828
171940
|
* 1. Present the CLI-provided MODIFIED-delta `diff`/`warning` fields as Change Detail evidence.
|
|
171829
171941
|
* 2. Color the unified diff body by line role (+/-/@@) without recomputing anything locally.
|
|
171830
171942
|
* 3. Render the exact upstream warning text beside its diff so a near-miss never swallows evidence.
|
|
171831
|
-
* 4. Gate the fetch on the detected admitted CLI's `requirementDiff` capability (
|
|
171832
|
-
* live mode: static snapshots and
|
|
171943
|
+
* 4. Gate the fetch on the detected admitted CLI's `requirementDiff` capability (the admitted
|
|
171944
|
+
* 1.12 line) and on live mode: static snapshots and retired sessions never issue the
|
|
171945
|
+
* transport call.
|
|
171833
171946
|
* 5. Degrade to the existing delta presentation when the fields are absent — no fabricated diff
|
|
171834
171947
|
* or warning may appear.
|
|
171835
171948
|
* 6. Mount directly inside the Evidence workspace detail pane: the Accordion shell is gone, the
|
|
@@ -171838,6 +171951,8 @@ function ArchivedValidationEvidence({ onChip } = {}) {
|
|
|
171838
171951
|
*
|
|
171839
171952
|
* Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
|
|
171840
171953
|
* Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
|
|
171954
|
+
* Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
|
|
171955
|
+
* Owner walkthrough correction (2026-09-04): every Evidence detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding); this replaces each layer's local weak header.
|
|
171841
171956
|
*/
|
|
171842
171957
|
function diffLineRole(line) {
|
|
171843
171958
|
if (line.startsWith("@@")) return "hunk";
|
|
@@ -171928,22 +172043,16 @@ function RequirementDiffsSection({ summary, children }) {
|
|
|
171928
172043
|
"data-evidence-section": "requirement-diffs",
|
|
171929
172044
|
"aria-label": "Requirement diffs",
|
|
171930
172045
|
className: "min-w-0",
|
|
171931
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
171932
|
-
|
|
171933
|
-
|
|
171934
|
-
className: "min-w-0 text-xs font-semibold",
|
|
171935
|
-
children: "Requirement diffs"
|
|
171936
|
-
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
171937
|
-
className: "text-muted-foreground min-w-0 text-[11px]",
|
|
171938
|
-
children: summary
|
|
171939
|
-
})]
|
|
172046
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceLayerHeader, {
|
|
172047
|
+
title: "Requirement diffs",
|
|
172048
|
+
summary
|
|
171940
172049
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
171941
|
-
className: "min-w-0
|
|
172050
|
+
className: "min-w-0 text-xs",
|
|
171942
172051
|
children
|
|
171943
172052
|
})]
|
|
171944
172053
|
});
|
|
171945
172054
|
}
|
|
171946
|
-
/** CLI MODIFIED-delta diff evidence for the Change Evidence workspace (live
|
|
172055
|
+
/** CLI MODIFIED-delta diff evidence for the Change Evidence workspace (admitted-line live sessions only). */
|
|
171947
172056
|
function ChangeDiffEvidence({ changeId, onChip }) {
|
|
171948
172057
|
const cli = useRootActionState().context?.cli;
|
|
171949
172058
|
const diffCapable = deriveOpenSpecCliCapabilities(cli?.available ? parseOpenSpecCliVersion(cli.version) : null).requirementDiff;
|
|
@@ -172017,9 +172126,13 @@ function ChangeDiffEvidence({ changeId, onChip }) {
|
|
|
172017
172126
|
if (!diffCapable) {
|
|
172018
172127
|
if (cli?.available !== true) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
|
|
172019
172128
|
summary: "CLI diff evidence",
|
|
172020
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
172129
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
172021
172130
|
className: "text-muted-foreground",
|
|
172022
|
-
children:
|
|
172131
|
+
children: [
|
|
172132
|
+
"Requirement diff evidence from `show --diff` appears here on admitted OpenSpec CLI sessions (",
|
|
172133
|
+
OPENSPEC_CLI_ACCEPTED_RANGE,
|
|
172134
|
+
") once the CLI is detected."
|
|
172135
|
+
]
|
|
172023
172136
|
})
|
|
172024
172137
|
});
|
|
172025
172138
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
|
|
@@ -172027,7 +172140,9 @@ function ChangeDiffEvidence({ changeId, onChip }) {
|
|
|
172027
172140
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
172028
172141
|
className: "text-muted-foreground",
|
|
172029
172142
|
children: [
|
|
172030
|
-
"Requirement diffs require an admitted OpenSpec CLI
|
|
172143
|
+
"Requirement diffs require an admitted OpenSpec CLI session (",
|
|
172144
|
+
OPENSPEC_CLI_ACCEPTED_RANGE,
|
|
172145
|
+
")",
|
|
172031
172146
|
cli.version ? ` (detected ${cli.version.trim()})` : "",
|
|
172032
172147
|
". This session's CLI does not declare the `show --diff` capability, so the delta presentation keeps using the captured local content."
|
|
172033
172148
|
]
|
|
@@ -172062,11 +172177,11 @@ function ChangeDiffEvidence({ changeId, onChip }) {
|
|
|
172062
172177
|
summary: "CLI diff evidence",
|
|
172063
172178
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172064
172179
|
className: "text-muted-foreground",
|
|
172065
|
-
children: "Requirement diff evidence from `show --diff` appears here on
|
|
172180
|
+
children: "Requirement diff evidence from `show --diff` appears here on admitted CLI sessions."
|
|
172066
172181
|
})
|
|
172067
172182
|
});
|
|
172068
172183
|
if (evidence.kind !== "executed") {
|
|
172069
|
-
const detail = evidence.reason === "command-failed" ? evidence.detail : evidence.reason === "capability" ? "The detected OpenSpec CLI does not declare the
|
|
172184
|
+
const detail = evidence.reason === "command-failed" ? evidence.detail : evidence.reason === "capability" ? "The detected OpenSpec CLI does not declare the requirement-diff capability." : "The planning root is unavailable, so requirement-diff evidence cannot be fetched.";
|
|
172070
172185
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
|
|
172071
172186
|
summary: "CLI evidence unavailable",
|
|
172072
172187
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -172149,6 +172264,7 @@ function ChangeDiffEvidence({ changeId, onChip }) {
|
|
|
172149
172264
|
*
|
|
172150
172265
|
* Original request (2026-08-03): use an Evidence tab to carry complete Change Detail information.
|
|
172151
172266
|
* Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
|
|
172267
|
+
* Owner walkthrough correction (2026-09-04): every Evidence detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding); this replaces each layer's local weak header.
|
|
172152
172268
|
*/
|
|
172153
172269
|
/** Shared section frame for the Evidence workspace detail pane; keeps the a11y heading. */
|
|
172154
172270
|
function WorkspaceSection({ id, title, summary, children, container = false }) {
|
|
@@ -172156,17 +172272,11 @@ function WorkspaceSection({ id, title, summary, children, container = false }) {
|
|
|
172156
172272
|
"data-evidence-section": id,
|
|
172157
172273
|
"aria-label": title,
|
|
172158
172274
|
className: container ? "@container min-w-0" : "min-w-0",
|
|
172159
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
172160
|
-
|
|
172161
|
-
|
|
172162
|
-
className: "min-w-0 text-xs font-semibold",
|
|
172163
|
-
children: title
|
|
172164
|
-
}), summary ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172165
|
-
className: "text-muted-foreground min-w-0 text-[11px]",
|
|
172166
|
-
children: summary
|
|
172167
|
-
}) : null]
|
|
172275
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceLayerHeader, {
|
|
172276
|
+
title,
|
|
172277
|
+
summary
|
|
172168
172278
|
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
172169
|
-
className: "min-w-0
|
|
172279
|
+
className: "min-w-0 text-xs",
|
|
172170
172280
|
children
|
|
172171
172281
|
})]
|
|
172172
172282
|
});
|
|
@@ -172454,20 +172564,502 @@ function EvidenceList({ label, values }) {
|
|
|
172454
172564
|
});
|
|
172455
172565
|
}
|
|
172456
172566
|
//#endregion
|
|
172567
|
+
//#region src/components/validation-findings-evidence.tsx
|
|
172568
|
+
/**
|
|
172569
|
+
* Orthogonal intents (updated 2026-09-04 Asia/Shanghai):
|
|
172570
|
+
* 1. Present the OpenSpec 1.12 `validate --report findings` document as typed CLI evidence.
|
|
172571
|
+
* 2. Attribute every item finding to its owning change: entries owned by the current change
|
|
172572
|
+
* render as the primary "This change" list, while entries owned by other active changes
|
|
172573
|
+
* stay in a clearly-labeled secondary disclosure with prominent change attribution — a
|
|
172574
|
+
* finding never presents as this change's finding just because the scope is shared.
|
|
172575
|
+
* 3. Render INFO as a first-class informational class, distinct from warnings and errors.
|
|
172576
|
+
* 4. Show the filtered view honestly: `returnedItems` beside the preserved full-run totals,
|
|
172577
|
+
* labeled as filtered, never presented as the complete validation result. Scope-level
|
|
172578
|
+
* counts are never filtered to the current change.
|
|
172579
|
+
* 5. Gate the affordance behind the admitted line's `findingsReport` capability: non-admitted
|
|
172580
|
+
* sessions get no findings action; static snapshots state the evidence is unavailable.
|
|
172581
|
+
* 6. Validate transport and findings payloads with the Core contract schemas, never shallow
|
|
172582
|
+
* guards, and keep the CLI-owned request-error envelope on the direct plane.
|
|
172583
|
+
*
|
|
172584
|
+
* Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
|
|
172585
|
+
* Owner walkthrough correction (2026-09-04): findings must attribute their owning change; the Evidence detail panel styling follows the vision review and every detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding) instead of a local weak header.
|
|
172586
|
+
*/
|
|
172587
|
+
function parseFindingsPayload(value) {
|
|
172588
|
+
const parsed = CliValidateFindingsResultSchema.safeParse(value);
|
|
172589
|
+
if (parsed.success) return isCliValidateFindings(parsed.data) ? {
|
|
172590
|
+
kind: "findings",
|
|
172591
|
+
findings: parsed.data
|
|
172592
|
+
} : {
|
|
172593
|
+
kind: "request-failure",
|
|
172594
|
+
failure: parsed.data
|
|
172595
|
+
};
|
|
172596
|
+
const document = CliValidateFindingsSchema.safeParse(value);
|
|
172597
|
+
return {
|
|
172598
|
+
kind: "malformed",
|
|
172599
|
+
schemaIssues: (document.success ? parsed.error : document.error).issues.map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`)
|
|
172600
|
+
};
|
|
172601
|
+
}
|
|
172602
|
+
/** Semantic level chip: box-radius geometry, distinct glyph per class, tinted never flooded. */
|
|
172603
|
+
var LEVEL_CHIP_CLASS = {
|
|
172604
|
+
INFO: "border-blue-600/40 bg-blue-500/5 text-blue-600 dark:text-blue-400",
|
|
172605
|
+
WARNING: "border-amber-600/40 bg-amber-500/5 text-amber-600 dark:text-amber-400",
|
|
172606
|
+
ERROR: "border-red-600/40 bg-red-500/5 text-red-600 dark:text-red-400"
|
|
172607
|
+
};
|
|
172608
|
+
var LEVEL_CHIP_GLYPH = {
|
|
172609
|
+
INFO: Info$1,
|
|
172610
|
+
WARNING: TriangleAlert,
|
|
172611
|
+
ERROR: OctagonAlert
|
|
172612
|
+
};
|
|
172613
|
+
function LevelChip({ level }) {
|
|
172614
|
+
const Glyph = LEVEL_CHIP_GLYPH[level];
|
|
172615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
172616
|
+
"data-findings-level": level,
|
|
172617
|
+
className: `inline-flex shrink-0 items-center gap-1 border px-1.5 py-0.5 text-[11px] font-semibold uppercase tracking-wide ${LEVEL_CHIP_CLASS[level]}`,
|
|
172618
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Glyph, {
|
|
172619
|
+
className: "h-3 w-3",
|
|
172620
|
+
"aria-hidden": true
|
|
172621
|
+
}), level]
|
|
172622
|
+
});
|
|
172623
|
+
}
|
|
172624
|
+
/**
|
|
172625
|
+
* One findings item as a header/body card. Each issue owns a header row (level chip, issue
|
|
172626
|
+
* path, item identity) and a neutral message body; multiple issues stack as divided rows.
|
|
172627
|
+
* The message itself never carries the level color — the chip is the only color carrier.
|
|
172628
|
+
*/
|
|
172629
|
+
function FindingCard({ item }) {
|
|
172630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("article", {
|
|
172631
|
+
"data-findings-item": item.id,
|
|
172632
|
+
className: "border-border bg-card min-w-0 overflow-hidden rounded border",
|
|
172633
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
172634
|
+
className: "border-border/60 m-0 list-none divide-y p-0",
|
|
172635
|
+
children: item.issues.map((issue, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
|
|
172636
|
+
"data-findings-issue": issue.level,
|
|
172637
|
+
className: "min-w-0",
|
|
172638
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
|
|
172639
|
+
className: "border-border flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 border-b px-2.5 py-1.5",
|
|
172640
|
+
children: [
|
|
172641
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LevelChip, { level: issue.level }),
|
|
172642
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172643
|
+
className: "text-foreground min-w-0 flex-1 basis-[6rem] font-mono text-xs [overflow-wrap:anywhere]",
|
|
172644
|
+
children: issue.path
|
|
172645
|
+
}),
|
|
172646
|
+
index === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
172647
|
+
className: "text-muted-foreground max-w-full shrink-0 text-right font-mono text-[11px] [overflow-wrap:anywhere]",
|
|
172648
|
+
children: [
|
|
172649
|
+
item.id,
|
|
172650
|
+
" · ",
|
|
172651
|
+
item.type,
|
|
172652
|
+
" · ",
|
|
172653
|
+
item.valid ? "valid" : "invalid"
|
|
172654
|
+
]
|
|
172655
|
+
}) : null
|
|
172656
|
+
]
|
|
172657
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172658
|
+
className: "text-foreground/90 px-2.5 py-2 text-xs leading-relaxed [overflow-wrap:anywhere]",
|
|
172659
|
+
children: issue.message
|
|
172660
|
+
})]
|
|
172661
|
+
}, index))
|
|
172662
|
+
})
|
|
172663
|
+
});
|
|
172664
|
+
}
|
|
172665
|
+
/** Compact count chip (box radius; pill geometry stays reserved for bare numeric counts). */
|
|
172666
|
+
function CountChip({ label, tone }) {
|
|
172667
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172668
|
+
className: cn$1("inline-flex shrink-0 items-center rounded border px-1.5 py-0.5 text-xs font-medium", tone === "passed" && "border-emerald-600/40 bg-emerald-500/5 text-emerald-700 dark:text-emerald-400", tone === "failed" && "border-red-600/40 bg-red-500/5 text-red-600 dark:text-red-400", tone === "muted" && "border-border bg-muted/50 text-muted-foreground"),
|
|
172669
|
+
children: label
|
|
172670
|
+
});
|
|
172671
|
+
}
|
|
172672
|
+
function RunButton$1({ pending, label, onRun }) {
|
|
172673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
172674
|
+
type: "button",
|
|
172675
|
+
onClick: onRun,
|
|
172676
|
+
disabled: pending,
|
|
172677
|
+
"aria-busy": pending || void 0,
|
|
172678
|
+
className: "border-border hover:bg-muted inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-xs disabled:opacity-50",
|
|
172679
|
+
children: [pending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, {
|
|
172680
|
+
className: "h-3.5 w-3.5 animate-spin",
|
|
172681
|
+
"aria-hidden": true
|
|
172682
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, {
|
|
172683
|
+
className: "h-3.5 w-3.5 shrink-0",
|
|
172684
|
+
"aria-hidden": true
|
|
172685
|
+
}), label]
|
|
172686
|
+
});
|
|
172687
|
+
}
|
|
172688
|
+
/**
|
|
172689
|
+
* Structure-agnostic section frame for the Evidence workspace detail pane: heading plus
|
|
172690
|
+
* summary facts stay on the record; the workspace, not a disclosure, owns reveal behavior.
|
|
172691
|
+
* The header follows the workspace's one header contract: rule, baseline padding, margin.
|
|
172692
|
+
*/
|
|
172693
|
+
function ValidationFindingsSection({ summary, children }) {
|
|
172694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
|
|
172695
|
+
"data-evidence-section": "validation-findings",
|
|
172696
|
+
"aria-label": "Validation findings",
|
|
172697
|
+
className: "min-w-0",
|
|
172698
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceLayerHeader, {
|
|
172699
|
+
title: "Validation findings",
|
|
172700
|
+
summary
|
|
172701
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
172702
|
+
className: "min-w-0 text-xs",
|
|
172703
|
+
children
|
|
172704
|
+
})]
|
|
172705
|
+
});
|
|
172706
|
+
}
|
|
172707
|
+
/**
|
|
172708
|
+
* On-demand, read-only validation findings evidence for the Change Evidence workspace.
|
|
172709
|
+
*
|
|
172710
|
+
* The findings report is a filtered view — only items with issues — over the same full-run
|
|
172711
|
+
* totals the complete validation report carries, so the section always presents
|
|
172712
|
+
* `returnedItems` beside the preserved totals and never claims to be the complete result.
|
|
172713
|
+
* The report covers the whole changes scope, so every item finding is attributed: the
|
|
172714
|
+
* current change's entries render as the primary list and other changes' entries stay in a
|
|
172715
|
+
* labeled secondary disclosure with the owning change id prominent.
|
|
172716
|
+
*/
|
|
172717
|
+
function ValidationFindingsEvidence({ changeId, onChip }) {
|
|
172718
|
+
const [report, setReport] = (0, import_react.useState)(null);
|
|
172719
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
172720
|
+
const [pending, setPending] = (0, import_react.useState)(false);
|
|
172721
|
+
const cli = useRootActionState().context?.cli;
|
|
172722
|
+
const staticMode = isStaticMode();
|
|
172723
|
+
const capabilities = deriveOpenSpecCliCapabilities(cli?.available ? parseOpenSpecCliVersion(cli.version) : null);
|
|
172724
|
+
const chip = (0, import_react.useMemo)(() => {
|
|
172725
|
+
if (staticMode) return {
|
|
172726
|
+
label: "unavailable",
|
|
172727
|
+
tone: "unavailable"
|
|
172728
|
+
};
|
|
172729
|
+
if (cli?.available === true && !capabilities.findingsReport) return {
|
|
172730
|
+
label: "unavailable",
|
|
172731
|
+
tone: "unavailable"
|
|
172732
|
+
};
|
|
172733
|
+
if (!report && !error) return null;
|
|
172734
|
+
const parsed = report ? parseFindingsPayload(report.data) : null;
|
|
172735
|
+
if (error || !parsed || parsed.kind === "malformed") return {
|
|
172736
|
+
label: "fail",
|
|
172737
|
+
tone: "negative"
|
|
172738
|
+
};
|
|
172739
|
+
if (parsed.kind === "request-failure") return {
|
|
172740
|
+
label: "fail",
|
|
172741
|
+
tone: "negative"
|
|
172742
|
+
};
|
|
172743
|
+
const findings = parsed.findings;
|
|
172744
|
+
return findings.summary.totals.failed > 0 ? {
|
|
172745
|
+
label: `${findings.summary.totals.failed} failed`,
|
|
172746
|
+
tone: "negative"
|
|
172747
|
+
} : {
|
|
172748
|
+
label: `${findings.report.returnedItems} findings`,
|
|
172749
|
+
tone: "neutral"
|
|
172750
|
+
};
|
|
172751
|
+
}, [
|
|
172752
|
+
capabilities.findingsReport,
|
|
172753
|
+
cli?.available,
|
|
172754
|
+
error,
|
|
172755
|
+
report,
|
|
172756
|
+
staticMode
|
|
172757
|
+
]);
|
|
172758
|
+
(0, import_react.useEffect)(() => {
|
|
172759
|
+
onChip?.(chip);
|
|
172760
|
+
}, [chip, onChip]);
|
|
172761
|
+
if (staticMode) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172762
|
+
summary: "Unavailable in static snapshot",
|
|
172763
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172764
|
+
className: "text-muted-foreground",
|
|
172765
|
+
children: "Validation findings are live CLI evidence and are not captured in this static snapshot."
|
|
172766
|
+
})
|
|
172767
|
+
});
|
|
172768
|
+
if (cli?.available === true && !capabilities.findingsReport) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172769
|
+
summary: "Unavailable on this CLI line",
|
|
172770
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
172771
|
+
className: "text-muted-foreground",
|
|
172772
|
+
children: [
|
|
172773
|
+
"Validation findings require the admitted OpenSpec CLI line (",
|
|
172774
|
+
OPENSPEC_CLI_ACCEPTED_RANGE,
|
|
172775
|
+
")",
|
|
172776
|
+
cli.version ? ` (detected ${cli.version.trim()})` : "",
|
|
172777
|
+
". This session's CLI does not declare the findings-report capability, so no command is offered."
|
|
172778
|
+
]
|
|
172779
|
+
})
|
|
172780
|
+
});
|
|
172781
|
+
const run = async () => {
|
|
172782
|
+
setPending(true);
|
|
172783
|
+
setError(null);
|
|
172784
|
+
setReport(null);
|
|
172785
|
+
try {
|
|
172786
|
+
const result = await trpcClient.cli.validate.mutate({
|
|
172787
|
+
kind: "findings",
|
|
172788
|
+
scope: "changes"
|
|
172789
|
+
});
|
|
172790
|
+
const transport = CliCommandTransportSchema.safeParse(result);
|
|
172791
|
+
if (transport.success) setReport({
|
|
172792
|
+
...transport.data,
|
|
172793
|
+
data: transport.data.data ?? null,
|
|
172794
|
+
payload: transport.data.payload ?? null
|
|
172795
|
+
});
|
|
172796
|
+
else setError("The validation findings transport returned an unrecognized result shape.");
|
|
172797
|
+
} catch (cause) {
|
|
172798
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
172799
|
+
} finally {
|
|
172800
|
+
setPending(false);
|
|
172801
|
+
}
|
|
172802
|
+
};
|
|
172803
|
+
if (!report && !error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172804
|
+
summary: "Not yet run",
|
|
172805
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
172806
|
+
className: "border-border bg-muted/20 max-w-[72ch] rounded-md border border-dashed p-6",
|
|
172807
|
+
children: pending ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172808
|
+
className: "flex items-center gap-2",
|
|
172809
|
+
role: "status",
|
|
172810
|
+
"data-findings-running": "",
|
|
172811
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, {
|
|
172812
|
+
className: "text-muted-foreground h-4 w-4 animate-spin",
|
|
172813
|
+
"aria-hidden": true
|
|
172814
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172815
|
+
className: "text-xs font-medium",
|
|
172816
|
+
children: "Running findings report…"
|
|
172817
|
+
})]
|
|
172818
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172819
|
+
className: "space-y-3",
|
|
172820
|
+
children: [
|
|
172821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172822
|
+
className: "text-xs font-semibold",
|
|
172823
|
+
children: "No findings loaded"
|
|
172824
|
+
}),
|
|
172825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172826
|
+
className: "text-muted-foreground",
|
|
172827
|
+
children: "Load the official CLI's validation findings to see advisory issues reported for the active changes in this scope — including archive-merge advisories. This is read-only evidence; nothing is repaired from here."
|
|
172828
|
+
}),
|
|
172829
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", {
|
|
172830
|
+
className: "border-border bg-muted rounded border px-1 py-0.5 font-mono text-[11px]",
|
|
172831
|
+
children: "openspec validate --report findings"
|
|
172832
|
+
}) }),
|
|
172833
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$1, {
|
|
172834
|
+
pending,
|
|
172835
|
+
label: "Load validation findings",
|
|
172836
|
+
onRun: () => void run()
|
|
172837
|
+
})
|
|
172838
|
+
]
|
|
172839
|
+
})
|
|
172840
|
+
})
|
|
172841
|
+
});
|
|
172842
|
+
const parsed = report ? parseFindingsPayload(report.data) : null;
|
|
172843
|
+
if (error || !parsed || parsed.kind === "malformed") {
|
|
172844
|
+
const schemaDiagnostic = parsed?.kind === "malformed" && parsed.schemaIssues.length > 0 ? parsed.schemaIssues.join("; ") : null;
|
|
172845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172846
|
+
summary: "CLI failure evidence",
|
|
172847
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172848
|
+
className: "space-y-2",
|
|
172849
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172850
|
+
className: "text-destructive flex items-start gap-2 break-words",
|
|
172851
|
+
role: "alert",
|
|
172852
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
|
|
172853
|
+
className: "mt-0.5 h-3.5 w-3.5 shrink-0",
|
|
172854
|
+
"aria-hidden": true
|
|
172855
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172856
|
+
className: "min-w-0 [overflow-wrap:anywhere]",
|
|
172857
|
+
children: error ?? report?.contractError ?? schemaDiagnostic ?? report?.stderr.trim() ?? "The validation findings command failed."
|
|
172858
|
+
})]
|
|
172859
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$1, {
|
|
172860
|
+
pending,
|
|
172861
|
+
label: "Rerun",
|
|
172862
|
+
onRun: () => void run()
|
|
172863
|
+
})]
|
|
172864
|
+
})
|
|
172865
|
+
});
|
|
172866
|
+
}
|
|
172867
|
+
if (parsed.kind === "request-failure") {
|
|
172868
|
+
const entries = parsed.failure.status;
|
|
172869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172870
|
+
summary: "CLI request failure",
|
|
172871
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172872
|
+
className: "space-y-2",
|
|
172873
|
+
children: [
|
|
172874
|
+
entries.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172875
|
+
"data-findings-request-error": entry.code,
|
|
172876
|
+
className: "text-destructive flex items-start gap-2 break-words",
|
|
172877
|
+
role: "alert",
|
|
172878
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
|
|
172879
|
+
className: "mt-0.5 h-3.5 w-3.5 shrink-0",
|
|
172880
|
+
"aria-hidden": true
|
|
172881
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
172882
|
+
className: "min-w-0 [overflow-wrap:anywhere]",
|
|
172883
|
+
children: [
|
|
172884
|
+
entry.code,
|
|
172885
|
+
": ",
|
|
172886
|
+
entry.message
|
|
172887
|
+
]
|
|
172888
|
+
})]
|
|
172889
|
+
}, index)),
|
|
172890
|
+
entries.some((entry) => entry.fix !== void 0) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
|
|
172891
|
+
className: "break-words",
|
|
172892
|
+
"data-findings-request-fix": true,
|
|
172893
|
+
children: ["CLI fix suggestion: ", entries.find((entry) => entry.fix !== void 0)?.fix]
|
|
172894
|
+
}) : null,
|
|
172895
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$1, {
|
|
172896
|
+
pending,
|
|
172897
|
+
label: "Rerun",
|
|
172898
|
+
onRun: () => void run()
|
|
172899
|
+
})
|
|
172900
|
+
]
|
|
172901
|
+
})
|
|
172902
|
+
});
|
|
172903
|
+
}
|
|
172904
|
+
const findings = parsed.findings;
|
|
172905
|
+
const totals = findings.summary.totals;
|
|
172906
|
+
const ownFindings = findings.itemFindings.filter((item) => item.id === changeId);
|
|
172907
|
+
const otherFindings = findings.itemFindings.filter((item) => item.id !== changeId);
|
|
172908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsSection, {
|
|
172909
|
+
summary: `Filtered view · ${findings.report.returnedItems} of ${findings.report.totalItems} items with findings`,
|
|
172910
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172911
|
+
className: "space-y-3",
|
|
172912
|
+
children: [
|
|
172913
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172914
|
+
className: "text-muted-foreground",
|
|
172915
|
+
"data-findings-filtered-note": true,
|
|
172916
|
+
children: "Filtered CLI evidence: only items that reported issues are listed. The complete validation result remains the full report; totals below are the full-run values the CLI preserved."
|
|
172917
|
+
}),
|
|
172918
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
|
|
172919
|
+
"data-findings-provenance": "",
|
|
172920
|
+
className: "@[28rem]:grid-cols-[150px_1fr] grid min-w-0 grid-cols-1 gap-x-3 gap-y-1",
|
|
172921
|
+
children: [
|
|
172922
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
172923
|
+
className: "text-muted-foreground",
|
|
172924
|
+
children: "Root"
|
|
172925
|
+
}),
|
|
172926
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
|
|
172927
|
+
className: "min-w-0 font-mono text-xs [overflow-wrap:anywhere]",
|
|
172928
|
+
children: findings.root.path
|
|
172929
|
+
}),
|
|
172930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
172931
|
+
className: "text-muted-foreground",
|
|
172932
|
+
children: "Exit status"
|
|
172933
|
+
}),
|
|
172934
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
|
|
172935
|
+
className: "min-w-0 font-mono text-xs",
|
|
172936
|
+
children: report?.exitCode === null || report?.exitCode === void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
172937
|
+
className: "text-muted-foreground",
|
|
172938
|
+
children: "—"
|
|
172939
|
+
}) : report.exitCode
|
|
172940
|
+
}),
|
|
172941
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
172942
|
+
className: "text-muted-foreground",
|
|
172943
|
+
children: "Items with findings"
|
|
172944
|
+
}),
|
|
172945
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", {
|
|
172946
|
+
className: "min-w-0 font-mono text-xs",
|
|
172947
|
+
children: [
|
|
172948
|
+
findings.report.returnedItems,
|
|
172949
|
+
" of ",
|
|
172950
|
+
findings.report.totalItems,
|
|
172951
|
+
" (",
|
|
172952
|
+
findings.report.scope,
|
|
172953
|
+
" ",
|
|
172954
|
+
"scope)"
|
|
172955
|
+
]
|
|
172956
|
+
})
|
|
172957
|
+
]
|
|
172958
|
+
}),
|
|
172959
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172960
|
+
className: "space-y-1.5",
|
|
172961
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
172962
|
+
className: "text-muted-foreground text-[11px]",
|
|
172963
|
+
children: "Full-run totals"
|
|
172964
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172965
|
+
className: "flex flex-wrap gap-1.5",
|
|
172966
|
+
"data-findings-totals": "",
|
|
172967
|
+
children: [
|
|
172968
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountChip, {
|
|
172969
|
+
label: `${totals.passed} passed`,
|
|
172970
|
+
tone: "passed"
|
|
172971
|
+
}),
|
|
172972
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountChip, {
|
|
172973
|
+
label: `${totals.failed} failed`,
|
|
172974
|
+
tone: totals.failed > 0 ? "failed" : "muted"
|
|
172975
|
+
}),
|
|
172976
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CountChip, {
|
|
172977
|
+
label: `${totals.items} items`,
|
|
172978
|
+
tone: "muted"
|
|
172979
|
+
})
|
|
172980
|
+
]
|
|
172981
|
+
})]
|
|
172982
|
+
}),
|
|
172983
|
+
findings.itemFindings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172984
|
+
className: "text-muted-foreground",
|
|
172985
|
+
children: "No item in this scope reported an issue. This filtered view lists issues only — it is not the complete validation result."
|
|
172986
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
172987
|
+
className: "space-y-2",
|
|
172988
|
+
"data-findings-own": "",
|
|
172989
|
+
children: [
|
|
172990
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h4", {
|
|
172991
|
+
className: "text-xs font-semibold",
|
|
172992
|
+
children: "This change"
|
|
172993
|
+
}),
|
|
172994
|
+
ownFindings.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FindingCard, { item }, item.id)),
|
|
172995
|
+
ownFindings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
172996
|
+
className: "text-muted-foreground",
|
|
172997
|
+
"data-findings-own-empty": "",
|
|
172998
|
+
children: "No findings for this change in the filtered scope. Other entries below belong to other active changes."
|
|
172999
|
+
}) : null
|
|
173000
|
+
]
|
|
173001
|
+
}), otherFindings.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
|
|
173002
|
+
"data-findings-other": "",
|
|
173003
|
+
className: "border-border rounded border",
|
|
173004
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("summary", {
|
|
173005
|
+
className: "cursor-pointer select-none px-2.5 py-2 text-xs font-medium",
|
|
173006
|
+
children: [
|
|
173007
|
+
"Findings from other active changes (",
|
|
173008
|
+
otherFindings.length,
|
|
173009
|
+
")"
|
|
173010
|
+
]
|
|
173011
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
173012
|
+
className: "border-border space-y-3 border-t px-2.5 py-2.5",
|
|
173013
|
+
children: otherFindings.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
173014
|
+
className: "min-w-0 space-y-1",
|
|
173015
|
+
"data-findings-other-item": "",
|
|
173016
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
173017
|
+
className: "text-foreground font-mono text-xs font-medium",
|
|
173018
|
+
children: item.id
|
|
173019
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FindingCard, { item })]
|
|
173020
|
+
}, item.id))
|
|
173021
|
+
})]
|
|
173022
|
+
}) : null] }),
|
|
173023
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("footer", {
|
|
173024
|
+
className: "border-border mt-4 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 border-t pt-3",
|
|
173025
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
|
|
173026
|
+
className: "text-muted-foreground font-mono text-[11px] [overflow-wrap:anywhere]",
|
|
173027
|
+
children: [
|
|
173028
|
+
"openspec validate --report findings · ",
|
|
173029
|
+
findings.report.scope,
|
|
173030
|
+
" scope"
|
|
173031
|
+
]
|
|
173032
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton$1, {
|
|
173033
|
+
pending,
|
|
173034
|
+
label: "Rerun",
|
|
173035
|
+
onRun: () => void run()
|
|
173036
|
+
})]
|
|
173037
|
+
})
|
|
173038
|
+
]
|
|
173039
|
+
})
|
|
173040
|
+
});
|
|
173041
|
+
}
|
|
173042
|
+
//#endregion
|
|
172457
173043
|
//#region src/components/evidence-workspace.tsx
|
|
172458
173044
|
/**
|
|
172459
|
-
* Orthogonal intents (
|
|
173045
|
+
* Orthogonal intents (updated 2026-09-04 Asia/Shanghai):
|
|
172460
173046
|
* 1. Own the Change Evidence tab's container-responsive list-detail workspace topology.
|
|
172461
173047
|
* 2. Preserve the decision-plane evidence layer order (summary/paths -> requirement diffs ->
|
|
172462
|
-
* archived validation -> CLI/raw payload) in keyboard-reachable
|
|
173048
|
+
* validation findings -> archived validation -> CLI/raw payload) in keyboard-reachable
|
|
173049
|
+
* list rows.
|
|
172463
173050
|
* 3. Derive row chips only from settled section facts; never fabricate counts or verdicts.
|
|
172464
173051
|
* 4. Keep the crowded drill presentational: the detail replaces the list with a back
|
|
172465
173052
|
* affordance, and back restores the list without unmounting settled evidence; focus
|
|
172466
173053
|
* follows the drill (row -> back affordance -> originating row) so keyboard users never
|
|
172467
173054
|
* land on a hidden element.
|
|
172468
173055
|
* 5. Keep sub-selection local runtime state — it never enters routes or browser storage.
|
|
173056
|
+
* 6. Separate the workspace planes visually: the list column is the muted rail and the
|
|
173057
|
+
* detail column is the card surface; detail prose caps its measure, and only the
|
|
173058
|
+
* selected row ever carries a row fill.
|
|
172469
173059
|
*
|
|
172470
173060
|
* Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
|
|
173061
|
+
* Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
|
|
173062
|
+
* Owner walkthrough correction (2026-09-04): findings must attribute their owning change; the Evidence detail panel styling follows the vision review and every detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding) instead of a local weak header.
|
|
172471
173063
|
*/
|
|
172472
173064
|
/**
|
|
172473
173065
|
* Spacious threshold: below this inline size the workspace collapses to one column and the
|
|
@@ -172518,10 +173110,14 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172518
173110
|
const pendingRestoreRowId = (0, import_react.useRef)(null);
|
|
172519
173111
|
const backHadFocus = (0, import_react.useRef)(false);
|
|
172520
173112
|
const [diffChip, setDiffChip] = (0, import_react.useState)(null);
|
|
173113
|
+
const [findingsChip, setFindingsChip] = (0, import_react.useState)(null);
|
|
172521
173114
|
const [validationChip, setValidationChip] = (0, import_react.useState)(null);
|
|
172522
173115
|
const handleDiffChip = (0, import_react.useCallback)((chip) => {
|
|
172523
173116
|
setDiffChip(chip);
|
|
172524
173117
|
}, []);
|
|
173118
|
+
const handleFindingsChip = (0, import_react.useCallback)((chip) => {
|
|
173119
|
+
setFindingsChip(chip);
|
|
173120
|
+
}, []);
|
|
172525
173121
|
const handleValidationChip = (0, import_react.useCallback)((chip) => {
|
|
172526
173122
|
setValidationChip(chip);
|
|
172527
173123
|
}, []);
|
|
@@ -172549,6 +173145,15 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172549
173145
|
onChip: handleDiffChip
|
|
172550
173146
|
})
|
|
172551
173147
|
},
|
|
173148
|
+
{
|
|
173149
|
+
id: "validation-findings",
|
|
173150
|
+
label: "Validation findings",
|
|
173151
|
+
chip: findingsChip,
|
|
173152
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ValidationFindingsEvidence, {
|
|
173153
|
+
changeId,
|
|
173154
|
+
onChip: handleFindingsChip
|
|
173155
|
+
})
|
|
173156
|
+
},
|
|
172552
173157
|
{
|
|
172553
173158
|
id: "archived-validation",
|
|
172554
173159
|
label: "Archived validation",
|
|
@@ -172560,7 +173165,9 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172560
173165
|
}, [
|
|
172561
173166
|
changeId,
|
|
172562
173167
|
diffChip,
|
|
173168
|
+
findingsChip,
|
|
172563
173169
|
handleDiffChip,
|
|
173170
|
+
handleFindingsChip,
|
|
172564
173171
|
handleValidationChip,
|
|
172565
173172
|
referenceEvidence,
|
|
172566
173173
|
status,
|
|
@@ -172608,7 +173215,7 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172608
173215
|
"aria-label": "Evidence sections",
|
|
172609
173216
|
"data-evidence-pane": "list",
|
|
172610
173217
|
hidden: !showList || void 0,
|
|
172611
|
-
className: cn$1("scrollbar-thin scrollbar-track-transparent border-border
|
|
173218
|
+
className: cn$1("scrollbar-thin scrollbar-track-transparent bg-muted/40 border-border @[40rem]:border-r min-h-0 min-w-0 overflow-y-auto overflow-x-hidden overscroll-contain", !showList && "hidden"),
|
|
172612
173219
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
172613
173220
|
className: "divide-border/20 m-0 list-none divide-y p-0",
|
|
172614
173221
|
children: sections.map((section) => {
|
|
@@ -172639,7 +173246,7 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172639
173246
|
"data-evidence-pane": "detail",
|
|
172640
173247
|
"data-change-evidence-scroll-owner": "",
|
|
172641
173248
|
hidden: !showDetail || void 0,
|
|
172642
|
-
className: cn$1("scrollbar-thin scrollbar-track-transparent min-h-0 min-w-0 overflow-y-auto overflow-x-hidden overscroll-contain", showDetail ? "flex flex-col" : "hidden"),
|
|
173249
|
+
className: cn$1("scrollbar-thin scrollbar-track-transparent bg-card min-h-0 min-w-0 overflow-y-auto overflow-x-hidden overscroll-contain", showDetail ? "flex flex-col" : "hidden"),
|
|
172643
173250
|
children: [!spacious && drilled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
172644
173251
|
ref: backRef,
|
|
172645
173252
|
type: "button",
|
|
@@ -172652,7 +173259,7 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172652
173259
|
backHadFocus.current = false;
|
|
172653
173260
|
},
|
|
172654
173261
|
onClick: backToList,
|
|
172655
|
-
className: "bg-
|
|
173262
|
+
className: "bg-card/95 border-border/60 text-muted-foreground hover:text-foreground focus-visible:ring-primary sticky top-0 z-10 flex min-h-9 w-full min-w-0 items-center gap-1.5 border-b px-3 text-xs outline-none backdrop-blur focus-visible:ring-2 focus-visible:ring-inset",
|
|
172656
173263
|
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, {
|
|
172657
173264
|
className: "h-3.5 w-3.5 shrink-0",
|
|
172658
173265
|
"aria-hidden": true
|
|
@@ -172660,7 +173267,7 @@ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
|
|
|
172660
173267
|
}) : null, sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
172661
173268
|
"data-evidence-detail": section.id,
|
|
172662
173269
|
hidden: section.id !== activeSection.id,
|
|
172663
|
-
className: "min-w-0 px-4 pb-
|
|
173270
|
+
className: "min-w-0 px-4 pb-6 pt-3 [&_p]:max-w-[88ch]",
|
|
172664
173271
|
children: section.content
|
|
172665
173272
|
}, section.id))]
|
|
172666
173273
|
})]
|
|
@@ -172919,7 +173526,8 @@ function RootActionNotice({ state }) {
|
|
|
172919
173526
|
* Owner correction (2026-08-03): move Actions inline with the title, unify subtitle badges, and localize unavailable Tooltips.
|
|
172920
173527
|
* Original request (2026-08-15): 刷新/解析中状态收敛为副标题行内的 shiny 徽章,不再占据 statusRegion 块。
|
|
172921
173528
|
* Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。" — the Evidence
|
|
172922
|
-
* tab gains the
|
|
173529
|
+
* tab gains the capability-gated CLI MODIFIED-delta diff evidence beside the existing layers.
|
|
173530
|
+
* Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进" — the Evidence tab gains the findings evidence section.
|
|
172923
173531
|
* Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
|
|
172924
173532
|
*/
|
|
172925
173533
|
function ChangeView() {
|
|
@@ -173116,7 +173724,7 @@ var CONFIG_GUIDE_STAGE_META = {
|
|
|
173116
173724
|
//#region src/components/config/config-guide.tsx
|
|
173117
173725
|
var ConfigGuideContext = (0, import_react.createContext)(null);
|
|
173118
173726
|
(0, import_react.lazy)(async () => {
|
|
173119
|
-
return { default: (await import("./config-guide-presentation-
|
|
173727
|
+
return { default: (await import("./config-guide-presentation-GWnVFKTW.js")).ConfigGuidePresentationLayer };
|
|
173120
173728
|
});
|
|
173121
173729
|
/** Access the root-owned adaptive Guide runtime. */
|
|
173122
173730
|
function useConfigGuide() {
|
|
@@ -178823,6 +179431,208 @@ function SettingsStatic() {
|
|
|
178823
179431
|
});
|
|
178824
179432
|
}
|
|
178825
179433
|
//#endregion
|
|
179434
|
+
//#region src/components/spec-validation-evidence.tsx
|
|
179435
|
+
/**
|
|
179436
|
+
* Orthogonal intents (created 2026-08-28 Asia/Shanghai):
|
|
179437
|
+
* 1. Present OpenSpec `validate --specs` and `validate <id> --type spec --json` as typed CLI evidence.
|
|
179438
|
+
* 2. Share one on-demand, read-only surface for the all-specs toolbar action and the owned-spec
|
|
179439
|
+
* detail action; OpenSpecUI never repairs or rewrites anything from here.
|
|
179440
|
+
* 3. Identify the evidence as unavailable in static snapshots instead of fabricating it.
|
|
179441
|
+
* 4. Validate transport and report payloads with the Core contract schemas, never shallow guards.
|
|
179442
|
+
*
|
|
179443
|
+
* Original request (2026-08-28): Specifications 列表右上角提供"校验全部 specs",单 spec 详情右上角提供单项校验。
|
|
179444
|
+
*/
|
|
179445
|
+
function parseValidationReport(value) {
|
|
179446
|
+
const parsed = CliValidateReportSchema.safeParse(value);
|
|
179447
|
+
if (parsed.success) return {
|
|
179448
|
+
report: parsed.data,
|
|
179449
|
+
schemaIssues: []
|
|
179450
|
+
};
|
|
179451
|
+
return {
|
|
179452
|
+
report: null,
|
|
179453
|
+
schemaIssues: parsed.error.issues.map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "<root>"}: ${issue.message}`)
|
|
179454
|
+
};
|
|
179455
|
+
}
|
|
179456
|
+
function IssueList({ issues }) {
|
|
179457
|
+
if (issues.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
179458
|
+
className: "text-muted-foreground",
|
|
179459
|
+
children: "No CLI issue reported."
|
|
179460
|
+
});
|
|
179461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
|
|
179462
|
+
className: "text-muted-foreground space-y-0.5",
|
|
179463
|
+
children: issues.map((issue, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", {
|
|
179464
|
+
className: "break-words",
|
|
179465
|
+
children: [
|
|
179466
|
+
issue.level,
|
|
179467
|
+
" · ",
|
|
179468
|
+
issue.path,
|
|
179469
|
+
" · ",
|
|
179470
|
+
issue.message
|
|
179471
|
+
]
|
|
179472
|
+
}, index))
|
|
179473
|
+
});
|
|
179474
|
+
}
|
|
179475
|
+
function RunButton({ pending, label, onRun }) {
|
|
179476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
|
|
179477
|
+
type: "button",
|
|
179478
|
+
onClick: onRun,
|
|
179479
|
+
disabled: pending,
|
|
179480
|
+
"aria-busy": pending || void 0,
|
|
179481
|
+
className: "border-border hover:bg-muted inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-xs disabled:opacity-50",
|
|
179482
|
+
children: [pending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, {
|
|
179483
|
+
className: "h-3.5 w-3.5 animate-spin",
|
|
179484
|
+
"aria-hidden": true
|
|
179485
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, {
|
|
179486
|
+
className: "h-3.5 w-3.5",
|
|
179487
|
+
"aria-hidden": true
|
|
179488
|
+
}), label]
|
|
179489
|
+
});
|
|
179490
|
+
}
|
|
179491
|
+
/**
|
|
179492
|
+
* On-demand spec-scope validation evidence. Mounts with its trigger aligned to the inline-end
|
|
179493
|
+
* of a page header; the typed report panel unfolds beneath it only after a run, so unexecuted
|
|
179494
|
+
* sessions render no verdict at all.
|
|
179495
|
+
*/
|
|
179496
|
+
function SpecValidationEvidence({ target }) {
|
|
179497
|
+
const [report, setReport] = (0, import_react.useState)(null);
|
|
179498
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
179499
|
+
const [pending, setPending] = (0, import_react.useState)(false);
|
|
179500
|
+
const staticMode = isStaticMode();
|
|
179501
|
+
const label = target.kind === "specs" ? "Validate specs" : "Validate this spec";
|
|
179502
|
+
if (staticMode) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
179503
|
+
className: "text-muted-foreground max-w-xs text-right text-xs",
|
|
179504
|
+
children: "Spec validation is live CLI evidence and is not captured in this static snapshot."
|
|
179505
|
+
});
|
|
179506
|
+
const run = async () => {
|
|
179507
|
+
setPending(true);
|
|
179508
|
+
setError(null);
|
|
179509
|
+
setReport(null);
|
|
179510
|
+
try {
|
|
179511
|
+
const input = target.kind === "specs" ? {
|
|
179512
|
+
kind: "scope",
|
|
179513
|
+
scope: "specs"
|
|
179514
|
+
} : {
|
|
179515
|
+
kind: "item",
|
|
179516
|
+
id: target.specId,
|
|
179517
|
+
type: "spec"
|
|
179518
|
+
};
|
|
179519
|
+
const result = await trpcClient.cli.validate.mutate(input);
|
|
179520
|
+
const transport = CliCommandTransportSchema.safeParse(result);
|
|
179521
|
+
if (transport.success) setReport({
|
|
179522
|
+
...transport.data,
|
|
179523
|
+
data: transport.data.data ?? null,
|
|
179524
|
+
payload: transport.data.payload ?? null
|
|
179525
|
+
});
|
|
179526
|
+
else setError("The spec validation transport returned an unrecognized result shape.");
|
|
179527
|
+
} catch (cause) {
|
|
179528
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
179529
|
+
} finally {
|
|
179530
|
+
setPending(false);
|
|
179531
|
+
}
|
|
179532
|
+
};
|
|
179533
|
+
if (!report && !error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
179534
|
+
pending,
|
|
179535
|
+
label,
|
|
179536
|
+
onRun: () => void run()
|
|
179537
|
+
});
|
|
179538
|
+
const parsed = report ? parseValidationReport(report.data) : {
|
|
179539
|
+
report: null,
|
|
179540
|
+
schemaIssues: []
|
|
179541
|
+
};
|
|
179542
|
+
const validationReport = parsed.report;
|
|
179543
|
+
if (error || !validationReport) {
|
|
179544
|
+
const schemaDiagnostic = parsed.schemaIssues.length > 0 ? parsed.schemaIssues.join("; ") : null;
|
|
179545
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179546
|
+
className: "border-border/60 w-full max-w-2xl self-end rounded border p-3 text-left",
|
|
179547
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179548
|
+
className: "text-destructive flex items-start gap-2 break-words",
|
|
179549
|
+
role: "alert",
|
|
179550
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
|
|
179551
|
+
className: "mt-0.5 h-3.5 w-3.5 shrink-0",
|
|
179552
|
+
"aria-hidden": true
|
|
179553
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
179554
|
+
className: "min-w-0 break-all",
|
|
179555
|
+
children: error ?? report?.contractError ?? schemaDiagnostic ?? report?.stderr.trim() ?? "The spec validation command failed."
|
|
179556
|
+
})]
|
|
179557
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
179558
|
+
className: "mt-2",
|
|
179559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
179560
|
+
pending,
|
|
179561
|
+
label: "Rerun",
|
|
179562
|
+
onRun: () => void run()
|
|
179563
|
+
})
|
|
179564
|
+
})]
|
|
179565
|
+
});
|
|
179566
|
+
}
|
|
179567
|
+
const failed = validationReport.summary.totals.failed;
|
|
179568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
179569
|
+
className: "border-border/60 w-full max-w-2xl self-end rounded border p-3 text-left",
|
|
179570
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179571
|
+
className: "space-y-3",
|
|
179572
|
+
children: [
|
|
179573
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
|
|
179574
|
+
className: "grid min-w-0 gap-x-3 gap-y-1",
|
|
179575
|
+
children: [
|
|
179576
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
179577
|
+
className: "text-muted-foreground",
|
|
179578
|
+
children: "Root"
|
|
179579
|
+
}),
|
|
179580
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
|
|
179581
|
+
className: "min-w-0 break-all font-mono",
|
|
179582
|
+
children: validationReport.root.path
|
|
179583
|
+
}),
|
|
179584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
179585
|
+
className: "text-muted-foreground",
|
|
179586
|
+
children: "Exit"
|
|
179587
|
+
}),
|
|
179588
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: report?.exitCode ?? "unknown" }),
|
|
179589
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
|
|
179590
|
+
className: "text-muted-foreground",
|
|
179591
|
+
children: "Totals"
|
|
179592
|
+
}),
|
|
179593
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", { children: [
|
|
179594
|
+
validationReport.summary.totals.passed,
|
|
179595
|
+
" passed · ",
|
|
179596
|
+
failed,
|
|
179597
|
+
" failed ·",
|
|
179598
|
+
" ",
|
|
179599
|
+
validationReport.summary.totals.items,
|
|
179600
|
+
" specs"
|
|
179601
|
+
] })
|
|
179602
|
+
]
|
|
179603
|
+
}),
|
|
179604
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
179605
|
+
className: "space-y-2",
|
|
179606
|
+
children: validationReport.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179607
|
+
className: "border-border/60 rounded border p-2",
|
|
179608
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179609
|
+
className: "flex min-w-0 items-center gap-2",
|
|
179610
|
+
children: [item.valid && item.issues.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleCheck, {
|
|
179611
|
+
className: "h-3.5 w-3.5 shrink-0 text-emerald-600",
|
|
179612
|
+
"aria-hidden": true
|
|
179613
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
|
|
179614
|
+
className: `h-3.5 w-3.5 shrink-0 ${item.valid ? "text-amber-600" : "text-destructive"}`,
|
|
179615
|
+
"aria-hidden": true
|
|
179616
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
179617
|
+
className: "min-w-0 break-all font-mono text-[11px]",
|
|
179618
|
+
children: item.id
|
|
179619
|
+
})]
|
|
179620
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
179621
|
+
className: "mt-1",
|
|
179622
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IssueList, { issues: item.issues })
|
|
179623
|
+
})]
|
|
179624
|
+
}, item.id))
|
|
179625
|
+
}),
|
|
179626
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RunButton, {
|
|
179627
|
+
pending,
|
|
179628
|
+
label: "Rerun",
|
|
179629
|
+
onRun: () => void run()
|
|
179630
|
+
})
|
|
179631
|
+
]
|
|
179632
|
+
})
|
|
179633
|
+
});
|
|
179634
|
+
}
|
|
179635
|
+
//#endregion
|
|
178826
179636
|
//#region src/routes/spec-list-continuity.ts
|
|
178827
179637
|
/**
|
|
178828
179638
|
* Orthogonal intents (created 2026-07-23 Asia/Shanghai):
|
|
@@ -178917,7 +179727,7 @@ function useSpecListContinuity(incomingSpecs, scope, containerRef) {
|
|
|
178917
179727
|
//#endregion
|
|
178918
179728
|
//#region src/routes/spec-list.tsx
|
|
178919
179729
|
/**
|
|
178920
|
-
* Orthogonal intents (updated 2026-08-
|
|
179730
|
+
* Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
|
|
178921
179731
|
* 1. Default the project Spec Catalog to writable Owned Specs.
|
|
178922
179732
|
* 2. Group direct read-only Referenced Specs by Store identity and preserve source-distinct Catalog policy.
|
|
178923
179733
|
* 3. Preserve complete recursive routes, collision-safe View Transition identity, and local row continuity.
|
|
@@ -178927,6 +179737,7 @@ function useSpecListContinuity(incomingSpecs, scope, containerRef) {
|
|
|
178927
179737
|
* Original request (2026-07-15): "Specs defaults to Owned and provides a Store-grouped Referenced view with immutable entries."
|
|
178928
179738
|
* Original request (2026-07-28): compact Catalog source and read-only metadata without hiding enumeration failures.
|
|
178929
179739
|
* Original request (2026-08-01): adapt OpenSpec 1.7 nested Spec ids such as `platform/auth`.
|
|
179740
|
+
* Original request (2026-08-28): Specifications 顶部右侧提供“校验全部 specs”动作。
|
|
178930
179741
|
*/
|
|
178931
179742
|
function readSpecListScopeState(state) {
|
|
178932
179743
|
if (typeof state !== "object" || state == null) return "owned";
|
|
@@ -178994,9 +179805,12 @@ function SpecList() {
|
|
|
178994
179805
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
178995
179806
|
className: "space-y-6 p-4",
|
|
178996
179807
|
children: [
|
|
178997
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("
|
|
178998
|
-
className: "
|
|
178999
|
-
children: [/* @__PURE__ */ (0, import_jsx_runtime.
|
|
179808
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179809
|
+
className: "flex flex-wrap items-center justify-between gap-3",
|
|
179810
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h1", {
|
|
179811
|
+
className: "font-nav flex items-center gap-2 text-2xl font-bold",
|
|
179812
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileText, { className: "h-6 w-6 shrink-0" }), "Specifications"]
|
|
179813
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpecValidationEvidence, { target: { kind: "specs" } })]
|
|
179000
179814
|
}),
|
|
179001
179815
|
errorAlert,
|
|
179002
179816
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
@@ -179187,14 +180001,16 @@ function SpecCatalogRow({ spec }) {
|
|
|
179187
180001
|
//#endregion
|
|
179188
180002
|
//#region src/routes/spec-view.tsx
|
|
179189
180003
|
/**
|
|
179190
|
-
* Orthogonal intents (updated 2026-
|
|
180004
|
+
* Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
|
|
179191
180005
|
* 1. Resolve owned and referenced Spec routes through compound identity.
|
|
179192
180006
|
* 2. Render owned Markdown through the existing document pipeline.
|
|
179193
180007
|
* 3. Render live CLI evidence and static snapshot conditions without synthesizing CLI or route-derived Store provenance.
|
|
179194
180008
|
* 4. Preserve collision-safe View Transition identity across source-distinct documents.
|
|
179195
180009
|
* 5. Retain successful detail content beside terminal document subscription errors.
|
|
180010
|
+
* 6. Offer owned-spec validation as header-inline-end CLI evidence; referenced specs stay read-only.
|
|
179196
180011
|
*
|
|
179197
180012
|
* Original request (2026-07-15): "Referenced Specs are navigable and searchable but visibly read-only."
|
|
180013
|
+
* Original request (2026-08-28): 单 spec 详情右上角提供单项校验动作。
|
|
179198
180014
|
*/
|
|
179199
180015
|
function SpecView() {
|
|
179200
180016
|
const { specId, storeId } = useParams({ strict: false });
|
|
@@ -179254,42 +180070,49 @@ function SpecLoading({ identity, title, subtitle }) {
|
|
|
179254
180070
|
})]
|
|
179255
180071
|
});
|
|
179256
180072
|
}
|
|
179257
|
-
function SpecHeader({ identity, title, subtitle, sourceRef, sharedDescriptor }) {
|
|
180073
|
+
function SpecHeader({ identity, title, subtitle, sourceRef, sharedDescriptor, actions }) {
|
|
179258
180074
|
const sourceLabel = subtitle ?? (identity.kind === "owned" ? `Owned · ${identity.specId}` : `Referenced from ${identity.storeId} · ${identity.specId}`);
|
|
179259
180075
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
179260
180076
|
className: "flex min-w-0 items-center gap-4",
|
|
179261
|
-
children: [
|
|
179262
|
-
|
|
179263
|
-
|
|
179264
|
-
|
|
179265
|
-
|
|
180077
|
+
children: [
|
|
180078
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(VTLink, {
|
|
180079
|
+
to: "/specs",
|
|
180080
|
+
state: (previous) => ({
|
|
180081
|
+
...previous,
|
|
180082
|
+
__specListScope: identity.kind
|
|
180083
|
+
}),
|
|
180084
|
+
vt: {
|
|
180085
|
+
source: sourceRef,
|
|
180086
|
+
sharedElements: sharedDescriptor
|
|
180087
|
+
},
|
|
180088
|
+
className: "hover:bg-muted shrink-0 rounded-md p-2",
|
|
180089
|
+
"aria-label": "Back to specifications",
|
|
180090
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, { className: "h-5 w-5" })
|
|
179266
180091
|
}),
|
|
179267
|
-
|
|
179268
|
-
|
|
179269
|
-
|
|
179270
|
-
|
|
179271
|
-
|
|
179272
|
-
|
|
179273
|
-
|
|
179274
|
-
|
|
179275
|
-
|
|
179276
|
-
|
|
179277
|
-
|
|
179278
|
-
|
|
179279
|
-
|
|
179280
|
-
|
|
179281
|
-
|
|
179282
|
-
className: "
|
|
179283
|
-
|
|
179284
|
-
...getSharedElementBinding(sharedDescriptor, "title"),
|
|
179285
|
-
className: "truncate",
|
|
179286
|
-
children: title
|
|
180092
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
|
|
180093
|
+
ref: sourceRef,
|
|
180094
|
+
...getSharedElementBinding(sharedDescriptor, "container"),
|
|
180095
|
+
className: "min-w-0",
|
|
180096
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h1", {
|
|
180097
|
+
className: "font-nav flex min-w-0 items-center gap-2 text-2xl font-bold",
|
|
180098
|
+
children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileText, {
|
|
180099
|
+
...getSharedElementBinding(sharedDescriptor, "icon"),
|
|
180100
|
+
className: "h-6 w-6 shrink-0"
|
|
180101
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
|
|
180102
|
+
...getSharedElementBinding(sharedDescriptor, "title"),
|
|
180103
|
+
className: "truncate",
|
|
180104
|
+
children: title
|
|
180105
|
+
})]
|
|
180106
|
+
}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
|
|
180107
|
+
className: "text-muted-foreground truncate",
|
|
180108
|
+
children: sourceLabel
|
|
179287
180109
|
})]
|
|
179288
|
-
}),
|
|
179289
|
-
|
|
179290
|
-
|
|
179291
|
-
|
|
179292
|
-
|
|
180110
|
+
}),
|
|
180111
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
|
|
180112
|
+
className: "ml-auto flex min-w-0 flex-col items-end gap-2",
|
|
180113
|
+
children: actions
|
|
180114
|
+
}) : null
|
|
180115
|
+
]
|
|
179293
180116
|
});
|
|
179294
180117
|
}
|
|
179295
180118
|
function OwnedSpecContent({ identity, spec, rawMarkdown, translationConfig, errorMessage }) {
|
|
@@ -179310,7 +180133,11 @@ function OwnedSpecContent({ identity, spec, rawMarkdown, translationConfig, erro
|
|
|
179310
180133
|
identity,
|
|
179311
180134
|
title: spec.name,
|
|
179312
180135
|
sourceRef: headerRef,
|
|
179313
|
-
sharedDescriptor
|
|
180136
|
+
sharedDescriptor,
|
|
180137
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpecValidationEvidence, { target: {
|
|
180138
|
+
kind: "spec",
|
|
180139
|
+
specId: identity.specId
|
|
180140
|
+
} })
|
|
179314
180141
|
}),
|
|
179315
180142
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MarkdownViewer, {
|
|
179316
180143
|
markdown: rawMarkdown,
|