@openspecui/web 9.0.3 → 11.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.
Files changed (72) hide show
  1. package/dist/assets/App-CRdki6ZH.css +1 -0
  2. package/dist/assets/{App-CvmsDCVQ.js → App-DJc144W-.js} +102 -101
  3. package/dist/assets/{main-ENsuRQWu.js → main-DXrIDd5i.js} +2 -2
  4. package/dist/assets/{trpc-WfwUyRJj.js → trpc-EqFJjKn0.js} +1 -1
  5. package/dist/index.html +1 -1
  6. package/dist-ssg/client/.vite/ssr-manifest.json +79 -29
  7. package/dist-ssg/client/assets/CanvasRenderer-CngPuJLR.js +1 -0
  8. package/dist-ssg/client/assets/WebGLRenderer-D6PAqEKt.js +1 -0
  9. package/dist-ssg/client/assets/WebGPURenderer-CtCVeRwN.js +1 -0
  10. package/dist-ssg/client/assets/browserAll-BiLg81NS.js +1 -0
  11. package/dist-ssg/client/assets/{config-guide-presentation-Cn3kSpXZ.js → config-guide-presentation-BcSY1KFl.js} +1 -1
  12. package/dist-ssg/client/assets/{dist-BVC-3Mz_.js → dist--KYFoBcy.js} +1 -1
  13. package/dist-ssg/client/assets/{dist-CfapX6Lr.js → dist-B6Pffk4D.js} +1 -1
  14. package/dist-ssg/client/assets/dist-BN2GrXVl.js +1 -0
  15. package/dist-ssg/client/assets/{dist-URgAfvaG.js → dist-C24XzhQ9.js} +1 -1
  16. package/dist-ssg/client/assets/{dist-DTfE1AGY.js → dist-C6Glwe3G.js} +1 -1
  17. package/dist-ssg/client/assets/{dist-BM1aVB3p.js → dist-DP2j-YyT.js} +1 -1
  18. package/dist-ssg/client/assets/{dist-D_8785UD.js → dist-D_u4DgCb.js} +1 -1
  19. package/dist-ssg/client/assets/{dist-bIKkmeGM.js → dist-DqLAJpLg.js} +1 -1
  20. package/dist-ssg/client/assets/dist-DqTWWRfT.js +1 -0
  21. package/dist-ssg/client/assets/{dist-DSbjfgtE.js → dist-WVAwgVsq.js} +1 -1
  22. package/dist-ssg/client/assets/dist-ZlYc7_kt.js +1 -0
  23. package/dist-ssg/client/assets/{dist-Dq7tP1jy.js → dist-iFk0rzRc.js} +1 -1
  24. package/dist-ssg/client/assets/{ghostty-web-CepiWfia.js → ghostty-web-lktg9S8z.js} +1 -1
  25. package/dist-ssg/client/assets/index-CDBo5TOs.css +1 -0
  26. package/dist-ssg/client/assets/index.ssg-n59gyR9q.js +1650 -0
  27. package/dist-ssg/client/assets/{init-BOhrbGmd.js → init-Cy2h-29G.js} +1 -1
  28. package/dist-ssg/client/assets/{trpc-CfpujRJ8.js → trpc-DxTuySH7.js} +1 -1
  29. package/dist-ssg/client/assets/webworkerAll-B5n4bM-i.js +1 -0
  30. package/dist-ssg/client/index.ssg.html +2 -2
  31. package/dist-ssg/server/assets/CanvasRenderer-D58O6peF.js +3 -0
  32. package/dist-ssg/server/assets/WebGLRenderer-CLVKAqNO.js +3 -0
  33. package/dist-ssg/server/assets/WebGPURenderer-D4vaKOO4.js +3 -0
  34. package/dist-ssg/server/assets/{browserAll-BJZwRDaI.js → browserAll-ByxW2BCo.js} +2 -2
  35. package/dist-ssg/server/assets/{config-guide-presentation-CcpWbzbF.js → config-guide-presentation-BfkVCRQq.js} +1 -1
  36. package/dist-ssg/server/assets/{dist-BbKu_y6W.js → dist-5xHpmSpA.js} +1 -1
  37. package/dist-ssg/server/assets/{dist-glvfDQXi.js → dist-7sF3GmjJ.js} +1 -1
  38. package/dist-ssg/server/assets/{dist-C7cu-Ohs.js → dist-BPIetWhy.js} +1 -1
  39. package/dist-ssg/server/assets/{dist-Cxmy4PRF.js → dist-C-7lPLui.js} +1 -1
  40. package/dist-ssg/server/assets/dist-CiijDa1h.js +3 -0
  41. package/dist-ssg/server/assets/{dist-CmkO24b2.js → dist-Cj2NABFW.js} +1 -1
  42. package/dist-ssg/server/assets/dist-CkT7sc-T.js +3 -0
  43. package/dist-ssg/server/assets/dist-Ct3YhJiO.js +3 -0
  44. package/dist-ssg/server/assets/{dist-BZbvCEXY.js → dist-DvJqEVFD.js} +1 -1
  45. package/dist-ssg/server/assets/{dist-CTDTyhyq.js → dist-DzYuWuV1.js} +1 -1
  46. package/dist-ssg/server/assets/{dist-C0TNMvo3.js → dist-j6yIDF4P.js} +1 -1
  47. package/dist-ssg/server/assets/{dist-FpVzh8vE.js → dist-wEaYViHh.js} +1 -1
  48. package/dist-ssg/server/assets/{entry-server-D-Z6rVrS.js → entry-server-DccPywiF.js} +1081 -365
  49. package/dist-ssg/server/assets/{init-CCY3tsKc.js → init-mk1myhk2.js} +1 -1
  50. package/dist-ssg/server/assets/trpc-BPMx2lHD.js +3 -0
  51. package/dist-ssg/server/assets/webworkerAll-5v7Fs7LO.js +4 -0
  52. package/dist-ssg/server/ssr-entry-manifest.json +24 -24
  53. package/package.json +3 -3
  54. package/dist/assets/App-CKmWaGbS.css +0 -1
  55. package/dist-ssg/client/assets/CanvasRenderer-BhcfZraw.js +0 -1
  56. package/dist-ssg/client/assets/WebGLRenderer-BMU-g2CE.js +0 -1
  57. package/dist-ssg/client/assets/WebGPURenderer-BAsbFOnm.js +0 -1
  58. package/dist-ssg/client/assets/browserAll-DzAH94Dz.js +0 -1
  59. package/dist-ssg/client/assets/dist-CdxtXLZp.js +0 -1
  60. package/dist-ssg/client/assets/dist-Dw6bnxbK.js +0 -1
  61. package/dist-ssg/client/assets/dist-nRw76b0P.js +0 -1
  62. package/dist-ssg/client/assets/index-CltZALZD.css +0 -1
  63. package/dist-ssg/client/assets/index.ssg-DAtF3E31.js +0 -1649
  64. package/dist-ssg/client/assets/webworkerAll-BPYJdLSv.js +0 -1
  65. package/dist-ssg/server/assets/CanvasRenderer-k_tFIFoA.js +0 -3
  66. package/dist-ssg/server/assets/WebGLRenderer-cfN96M_D.js +0 -3
  67. package/dist-ssg/server/assets/WebGPURenderer-moX8CQUm.js +0 -3
  68. package/dist-ssg/server/assets/dist-Bosp3yvI.js +0 -3
  69. package/dist-ssg/server/assets/dist-CgFGYGuV.js +0 -3
  70. package/dist-ssg/server/assets/dist-DaxZJMDX.js +0 -3
  71. package/dist-ssg/server/assets/trpc-4dLqTVBm.js +0 -3
  72. package/dist-ssg/server/assets/webworkerAll-DVUDp5xO.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-4dLqTVBm.js");
30911
+ const { trpcClient } = await import("./trpc-BPMx2lHD.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-4dLqTVBm.js").then(({ trpcClient }) => trpcClient.kv.set.mutate({
31054
+ import("./trpc-BPMx2lHD.js").then(({ trpcClient }) => trpcClient.kv.set.mutate({
31055
31055
  key: this.storageKey,
31056
31056
  value: {
31057
31057
  mainTabs: this.state.mainTabs,
@@ -38940,190 +38940,6 @@ var R$2 = class R$2 {
38940
38940
  function F$1(t) {
38941
38941
  throw new I$2(t);
38942
38942
  }
38943
- //#endregion
38944
- //#region ../core/src/cli-contracts/command-result.ts
38945
- /**
38946
- * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
38947
- * 1. Preserve every process-level fact from an OpenSpec CLI invocation.
38948
- * 2. Validate command payloads without discarding the raw JSON document.
38949
- * 3. Surface contract drift separately from CLI command failure.
38950
- * 4. Provide the runtime transport-envelope schema for browser evidence boundaries.
38951
- *
38952
- * Original request (2026-07-15): "对新增字段保持可扩展,对必需语义严格验证。"
38953
- * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
38954
- */
38955
- /** Runtime schema for one JSON value retained verbatim from CLI stdout. */
38956
- var CliJsonValueSchema$1 = lazyType(() => unionType([
38957
- stringType(),
38958
- numberType(),
38959
- booleanType(),
38960
- nullType(),
38961
- arrayType(CliJsonValueSchema$1),
38962
- recordType(stringType(), CliJsonValueSchema$1)
38963
- ]));
38964
- /** Runtime transport envelope for one CLI command result. */
38965
- var CliCommandTransportSchema = objectType({
38966
- success: booleanType(),
38967
- stdout: stringType(),
38968
- stderr: stringType(),
38969
- exitCode: numberType().int().nullable(),
38970
- data: CliJsonValueSchema$1.nullable(),
38971
- payload: CliJsonValueSchema$1.nullable(),
38972
- diagnostics: arrayType(CliDiagnosticSchema),
38973
- contractError: stringType().optional()
38974
- });
38975
- //#endregion
38976
- //#region ../core/src/cli-contracts/schema-resolution.ts
38977
- /**
38978
- * Orthogonal intents (created 2026-08-15 Asia/Shanghai):
38979
- * 1. Decode `schemas --json` as a success-array or selected-Root failure sum type.
38980
- * 2. Keep the 1.9 failure envelope's diagnostics and absent Root distinct from an empty catalog.
38981
- * 3. Reuse the shared SchemaInfo entry shape across success and failure envelopes.
38982
- * 4. Keep the sum type importable from browser-safe Core consumers without workflow contracts.
38983
- *
38984
- * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
38985
- */
38986
- /** One workflow schema discovered by the CLI-selected OpenSpec runtime. */
38987
- var CliSchemaInfoSchema = objectType({
38988
- name: stringType(),
38989
- description: stringType().optional(),
38990
- artifacts: arrayType(stringType()),
38991
- source: enumType([
38992
- "project",
38993
- "user",
38994
- "package"
38995
- ])
38996
- }).passthrough();
38997
- unionType([arrayType(CliSchemaInfoSchema), objectType({
38998
- schemas: arrayType(CliSchemaInfoSchema),
38999
- root: nullType(),
39000
- status: arrayType(CliDiagnosticSchema).min(1)
39001
- }).passthrough()]);
39002
- //#endregion
39003
- //#region ../core/src/cli-contracts/store.ts
39004
- /**
39005
- * Orthogonal intents (created 2026-07-15 Asia/Shanghai):
39006
- * 1. Model the snake_case Store command family.
39007
- * 2. Model root Doctor and Context relationship projections.
39008
- * 3. Preserve healthy empty Stores and diagnostic failure null-shapes.
39009
- *
39010
- * Original request (2026-07-15): "Store/Context/Doctor 的 snake_case 与 workflow 的 camelCase 必须按官方合同处理。"
39011
- */
39012
- /** Registered Store identity and canonical root emitted by the CLI. */
39013
- var CliStoreSchema = objectType({
39014
- id: stringType(),
39015
- root: stringType(),
39016
- metadata_path: stringType().optional()
39017
- }).passthrough();
39018
- /** Strict typed result of the CLI Store-list JSON command. */
39019
- var CliStoreListSchema = objectType({
39020
- stores: arrayType(CliStoreSchema),
39021
- status: arrayType(CliDiagnosticSchema)
39022
- }).passthrough();
39023
- var CliStoreRegistryMutationSchema = objectType({
39024
- path: stringType(),
39025
- registered: booleanType(),
39026
- already_registered: booleanType()
39027
- }).passthrough();
39028
- var CliStoreGitMutationSchema = objectType({
39029
- is_repository: booleanType(),
39030
- initialized: booleanType(),
39031
- committed: booleanType()
39032
- }).passthrough();
39033
- /** Strict Store setup/register mutation result. */
39034
- var CliStoreMutationSchema = objectType({
39035
- store: CliStoreSchema.nullable(),
39036
- registry: CliStoreRegistryMutationSchema.nullable(),
39037
- git: CliStoreGitMutationSchema.nullable(),
39038
- created_files: arrayType(stringType()),
39039
- status: arrayType(CliDiagnosticSchema)
39040
- }).passthrough();
39041
- var CliStoreRegistryCleanupSchema = objectType({
39042
- path: stringType(),
39043
- removed: booleanType()
39044
- }).passthrough();
39045
- var CliStoreFilesCleanupSchema = objectType({
39046
- deleted: booleanType(),
39047
- deleted_path: stringType().nullable(),
39048
- left_on_disk: stringType().nullable()
39049
- }).passthrough();
39050
- /** Strict Store unregister/remove cleanup result. */
39051
- var CliStoreCleanupSchema = objectType({
39052
- store: CliStoreSchema.nullable(),
39053
- registry: CliStoreRegistryCleanupSchema.nullable(),
39054
- files: CliStoreFilesCleanupSchema.nullable(),
39055
- status: arrayType(CliDiagnosticSchema)
39056
- }).passthrough();
39057
- var CliPresenceSchema = objectType({ present: booleanType().nullable() }).passthrough();
39058
- var CliOpenSpecRootInspectionSchema = objectType({
39059
- present: booleanType().nullable(),
39060
- config: CliPresenceSchema,
39061
- specs: CliPresenceSchema,
39062
- changes: CliPresenceSchema,
39063
- archive: CliPresenceSchema,
39064
- healthy: booleanType(),
39065
- status: arrayType(CliDiagnosticSchema)
39066
- }).passthrough();
39067
- var CliStoreMetadataSchema = objectType({
39068
- present: booleanType().nullable(),
39069
- valid: booleanType().nullable(),
39070
- id: stringType().nullable().optional(),
39071
- remote: stringType().nullable().optional()
39072
- }).passthrough();
39073
- var CliStoreGitInspectionSchema = objectType({
39074
- is_repository: booleanType().nullable(),
39075
- has_commits: booleanType().nullable(),
39076
- has_uncommitted_changes: booleanType().nullable(),
39077
- has_remote: booleanType().nullable(),
39078
- origin_url: stringType().nullable()
39079
- }).passthrough();
39080
- /** Strict typed result of the CLI Store Doctor JSON command. */
39081
- var CliStoreDoctorSchema = objectType({
39082
- stores: arrayType(CliStoreSchema.extend({
39083
- openspec_root: CliOpenSpecRootInspectionSchema,
39084
- metadata: CliStoreMetadataSchema,
39085
- git: CliStoreGitInspectionSchema,
39086
- status: arrayType(CliDiagnosticSchema)
39087
- }).passthrough()),
39088
- status: arrayType(CliDiagnosticSchema)
39089
- }).passthrough();
39090
- var CliDoctorRootSchema = CliRootSchema.extend({
39091
- healthy: booleanType(),
39092
- status: arrayType(CliDiagnosticSchema)
39093
- }).passthrough();
39094
- var CliDoctorStoreSchema = objectType({
39095
- id: stringType(),
39096
- metadata: CliStoreMetadataSchema,
39097
- origin_url: stringType().optional(),
39098
- status: arrayType(CliDiagnosticSchema)
39099
- }).passthrough();
39100
- objectType({
39101
- root: CliDoctorRootSchema.nullable(),
39102
- store: CliDoctorStoreSchema.nullable(),
39103
- references: arrayType(CliDoctorReferenceEntrySchema),
39104
- status: arrayType(CliDiagnosticSchema)
39105
- }).passthrough();
39106
- var CliContextRootSchema = CliRootSchema.extend({ role: literalType("openspec_root") }).passthrough();
39107
- var CliContextMemberSchema = objectType({
39108
- role: literalType("referenced_store"),
39109
- id: stringType(),
39110
- path: stringType().optional(),
39111
- remote: stringType().optional(),
39112
- fetch: stringType().optional(),
39113
- status: arrayType(CliDiagnosticSchema)
39114
- }).passthrough();
39115
- objectType({
39116
- root: CliContextRootSchema.nullable(),
39117
- members: arrayType(CliContextMemberSchema),
39118
- status: arrayType(CliDiagnosticSchema)
39119
- }).passthrough();
39120
- unionType([
39121
- CliStoreMutationSchema,
39122
- CliStoreCleanupSchema,
39123
- CliStoreListSchema,
39124
- CliStoreDoctorSchema,
39125
- CliDiagnosticFailureSchema
39126
- ]);
39127
38943
  objectType({
39128
38944
  changes: arrayType(objectType({
39129
38945
  name: stringType(),
@@ -39176,6 +38992,7 @@ var CliTemplateEntrySchema = objectType({
39176
38992
  ])
39177
38993
  }).passthrough();
39178
38994
  recordType(CliTemplateEntrySchema);
38995
+ /** One requirement body shared by Spec documents and Change deltas. */
39179
38996
  var CliSpecRequirementSchema = objectType({
39180
38997
  text: stringType(),
39181
38998
  scenarios: arrayType(objectType({ rawText: stringType() }).passthrough())
@@ -39230,7 +39047,14 @@ var CliStatusArtifactSchema = objectType({
39230
39047
  requires: arrayType(stringType()),
39231
39048
  missingDeps: arrayType(stringType()).optional()
39232
39049
  }).passthrough();
39233
- unionType([objectType({
39050
+ /**
39051
+ * Root-less Status payload fields for one OpenSpec change.
39052
+ *
39053
+ * The single-change command attaches `root` itself; the OpenSpec 1.11 batch
39054
+ * envelope (`status --all --json`) reuses exactly these fields per entry while
39055
+ * the envelope owns the single root.
39056
+ */
39057
+ var CliWorkflowStatusFieldsSchema = objectType({
39234
39058
  changeName: stringType(),
39235
39059
  schemaName: stringType(),
39236
39060
  planningHome: CliPlanningHomeSchema,
@@ -39241,9 +39065,9 @@ unionType([objectType({
39241
39065
  applyRequires: arrayType(stringType()),
39242
39066
  nextSteps: arrayType(stringType()),
39243
39067
  actionContext: CliActionContextSchema,
39244
- artifacts: arrayType(CliStatusArtifactSchema),
39245
- root: CliRootSchema
39246
- }).passthrough(), CliDiagnosticFailureSchema]);
39068
+ artifacts: arrayType(CliStatusArtifactSchema)
39069
+ }).passthrough();
39070
+ unionType([CliWorkflowStatusFieldsSchema.extend({ root: CliRootSchema }).passthrough(), CliDiagnosticFailureSchema]);
39247
39071
  var CliInstructionDependencySchema = objectType({
39248
39072
  id: stringType(),
39249
39073
  done: booleanType(),
@@ -39355,6 +39179,245 @@ objectType({
39355
39179
  root: CliRootSchema.optional(),
39356
39180
  status: arrayType(CliDiagnosticSchema).optional()
39357
39181
  }).passthrough();
39182
+ objectType({
39183
+ changes: arrayType(unionType([CliWorkflowStatusFieldsSchema, objectType({
39184
+ changeName: stringType(),
39185
+ status: arrayType(CliDiagnosticSchema).min(1)
39186
+ }).passthrough()])),
39187
+ root: CliRootSchema.nullable(),
39188
+ message: literalType("No active changes.").optional(),
39189
+ status: arrayType(CliDiagnosticSchema).optional()
39190
+ }).passthrough();
39191
+ //#endregion
39192
+ //#region ../core/src/cli-contracts/command-result.ts
39193
+ /**
39194
+ * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
39195
+ * 1. Preserve every process-level fact from an OpenSpec CLI invocation.
39196
+ * 2. Validate command payloads without discarding the raw JSON document.
39197
+ * 3. Surface contract drift separately from CLI command failure.
39198
+ * 4. Provide the runtime transport-envelope schema for browser evidence boundaries.
39199
+ *
39200
+ * Original request (2026-07-15): "对新增字段保持可扩展,对必需语义严格验证。"
39201
+ * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
39202
+ */
39203
+ /** Runtime schema for one JSON value retained verbatim from CLI stdout. */
39204
+ var CliJsonValueSchema$1 = lazyType(() => unionType([
39205
+ stringType(),
39206
+ numberType(),
39207
+ booleanType(),
39208
+ nullType(),
39209
+ arrayType(CliJsonValueSchema$1),
39210
+ recordType(stringType(), CliJsonValueSchema$1)
39211
+ ]));
39212
+ /** Runtime transport envelope for one CLI command result. */
39213
+ var CliCommandTransportSchema = objectType({
39214
+ success: booleanType(),
39215
+ stdout: stringType(),
39216
+ stderr: stringType(),
39217
+ exitCode: numberType().int().nullable(),
39218
+ data: CliJsonValueSchema$1.nullable(),
39219
+ payload: CliJsonValueSchema$1.nullable(),
39220
+ diagnostics: arrayType(CliDiagnosticSchema),
39221
+ contractError: stringType().optional()
39222
+ });
39223
+ //#endregion
39224
+ //#region ../core/src/cli-contracts/schema-resolution.ts
39225
+ /**
39226
+ * Orthogonal intents (created 2026-08-15 Asia/Shanghai):
39227
+ * 1. Decode `schemas --json` as a success-array or selected-Root failure sum type.
39228
+ * 2. Keep the 1.9 failure envelope's diagnostics and absent Root distinct from an empty catalog.
39229
+ * 3. Reuse the shared SchemaInfo entry shape across success and failure envelopes.
39230
+ * 4. Keep the sum type importable from browser-safe Core consumers without workflow contracts.
39231
+ *
39232
+ * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
39233
+ */
39234
+ /** One workflow schema discovered by the CLI-selected OpenSpec runtime. */
39235
+ var CliSchemaInfoSchema = objectType({
39236
+ name: stringType(),
39237
+ description: stringType().optional(),
39238
+ artifacts: arrayType(stringType()),
39239
+ source: enumType([
39240
+ "project",
39241
+ "user",
39242
+ "package"
39243
+ ])
39244
+ }).passthrough();
39245
+ unionType([arrayType(CliSchemaInfoSchema), objectType({
39246
+ schemas: arrayType(CliSchemaInfoSchema),
39247
+ root: nullType(),
39248
+ status: arrayType(CliDiagnosticSchema).min(1)
39249
+ }).passthrough()]);
39250
+ //#endregion
39251
+ //#region ../core/src/cli-contracts/show-diff.ts
39252
+ /**
39253
+ * Orthogonal intents (created 2026-08-28 Asia/Shanghai):
39254
+ * 1. Model the OpenSpec 1.11 `show <change> --json --diff` success payload as separately
39255
+ * fetched CLI evidence; the diff is never recomputed or backfilled locally.
39256
+ * 2. Document `diff`/`warning` as MODIFIED-only upstream additions; ADDED, REMOVED, and
39257
+ * RENAMED deltas are unchanged by `--diff`, and a delta outside MODIFIED that carries
39258
+ * either field is rejected as contract drift instead of parsed as tolerated evidence.
39259
+ * 3. Keep the shared diagnostic failure union for root-selection and unknown-item failures.
39260
+ *
39261
+ * Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
39262
+ */
39263
+ /** One JSON delta of a change, carrying the extra fields `--diff` adds to MODIFIED entries. */
39264
+ var CliShowChangeDeltaSchema = objectType({
39265
+ spec: stringType(),
39266
+ operation: enumType([
39267
+ "ADDED",
39268
+ "MODIFIED",
39269
+ "REMOVED",
39270
+ "RENAMED"
39271
+ ]),
39272
+ description: stringType().optional(),
39273
+ requirement: CliSpecRequirementSchema.optional(),
39274
+ requirements: arrayType(CliSpecRequirementSchema).optional(),
39275
+ rename: objectType({
39276
+ from: stringType(),
39277
+ to: stringType()
39278
+ }).optional(),
39279
+ diff: stringType().optional(),
39280
+ warning: stringType().optional()
39281
+ }).passthrough().superRefine((delta, ctx) => {
39282
+ if (delta.operation === "MODIFIED") return;
39283
+ for (const field of ["diff", "warning"]) if (delta[field] !== void 0) ctx.addIssue({
39284
+ code: ZodIssueCode.custom,
39285
+ path: [field],
39286
+ message: `Only MODIFIED deltas carry ${field} evidence; ${delta.operation} deltas never do.`
39287
+ });
39288
+ });
39289
+ unionType([objectType({
39290
+ id: stringType(),
39291
+ title: stringType(),
39292
+ deltaCount: numberType(),
39293
+ deltas: arrayType(CliShowChangeDeltaSchema),
39294
+ root: CliRootSchema
39295
+ }).passthrough(), CliDiagnosticFailureSchema]);
39296
+ //#endregion
39297
+ //#region ../core/src/cli-contracts/store.ts
39298
+ /**
39299
+ * Orthogonal intents (created 2026-07-15 Asia/Shanghai):
39300
+ * 1. Model the snake_case Store command family.
39301
+ * 2. Model root Doctor and Context relationship projections.
39302
+ * 3. Preserve healthy empty Stores and diagnostic failure null-shapes.
39303
+ *
39304
+ * Original request (2026-07-15): "Store/Context/Doctor 的 snake_case 与 workflow 的 camelCase 必须按官方合同处理。"
39305
+ */
39306
+ /** Registered Store identity and canonical root emitted by the CLI. */
39307
+ var CliStoreSchema = objectType({
39308
+ id: stringType(),
39309
+ root: stringType(),
39310
+ metadata_path: stringType().optional()
39311
+ }).passthrough();
39312
+ /** Strict typed result of the CLI Store-list JSON command. */
39313
+ var CliStoreListSchema = objectType({
39314
+ stores: arrayType(CliStoreSchema),
39315
+ status: arrayType(CliDiagnosticSchema)
39316
+ }).passthrough();
39317
+ var CliStoreRegistryMutationSchema = objectType({
39318
+ path: stringType(),
39319
+ registered: booleanType(),
39320
+ already_registered: booleanType()
39321
+ }).passthrough();
39322
+ var CliStoreGitMutationSchema = objectType({
39323
+ is_repository: booleanType(),
39324
+ initialized: booleanType(),
39325
+ committed: booleanType()
39326
+ }).passthrough();
39327
+ /** Strict Store setup/register mutation result. */
39328
+ var CliStoreMutationSchema = objectType({
39329
+ store: CliStoreSchema.nullable(),
39330
+ registry: CliStoreRegistryMutationSchema.nullable(),
39331
+ git: CliStoreGitMutationSchema.nullable(),
39332
+ created_files: arrayType(stringType()),
39333
+ status: arrayType(CliDiagnosticSchema)
39334
+ }).passthrough();
39335
+ var CliStoreRegistryCleanupSchema = objectType({
39336
+ path: stringType(),
39337
+ removed: booleanType()
39338
+ }).passthrough();
39339
+ var CliStoreFilesCleanupSchema = objectType({
39340
+ deleted: booleanType(),
39341
+ deleted_path: stringType().nullable(),
39342
+ left_on_disk: stringType().nullable()
39343
+ }).passthrough();
39344
+ /** Strict Store unregister/remove cleanup result. */
39345
+ var CliStoreCleanupSchema = objectType({
39346
+ store: CliStoreSchema.nullable(),
39347
+ registry: CliStoreRegistryCleanupSchema.nullable(),
39348
+ files: CliStoreFilesCleanupSchema.nullable(),
39349
+ status: arrayType(CliDiagnosticSchema)
39350
+ }).passthrough();
39351
+ var CliPresenceSchema = objectType({ present: booleanType().nullable() }).passthrough();
39352
+ var CliOpenSpecRootInspectionSchema = objectType({
39353
+ present: booleanType().nullable(),
39354
+ config: CliPresenceSchema,
39355
+ specs: CliPresenceSchema,
39356
+ changes: CliPresenceSchema,
39357
+ archive: CliPresenceSchema,
39358
+ healthy: booleanType(),
39359
+ status: arrayType(CliDiagnosticSchema)
39360
+ }).passthrough();
39361
+ var CliStoreMetadataSchema = objectType({
39362
+ present: booleanType().nullable(),
39363
+ valid: booleanType().nullable(),
39364
+ id: stringType().nullable().optional(),
39365
+ remote: stringType().nullable().optional()
39366
+ }).passthrough();
39367
+ var CliStoreGitInspectionSchema = objectType({
39368
+ is_repository: booleanType().nullable(),
39369
+ has_commits: booleanType().nullable(),
39370
+ has_uncommitted_changes: booleanType().nullable(),
39371
+ has_remote: booleanType().nullable(),
39372
+ origin_url: stringType().nullable()
39373
+ }).passthrough();
39374
+ /** Strict typed result of the CLI Store Doctor JSON command. */
39375
+ var CliStoreDoctorSchema = objectType({
39376
+ stores: arrayType(CliStoreSchema.extend({
39377
+ openspec_root: CliOpenSpecRootInspectionSchema,
39378
+ metadata: CliStoreMetadataSchema,
39379
+ git: CliStoreGitInspectionSchema,
39380
+ status: arrayType(CliDiagnosticSchema)
39381
+ }).passthrough()),
39382
+ status: arrayType(CliDiagnosticSchema)
39383
+ }).passthrough();
39384
+ var CliDoctorRootSchema = CliRootSchema.extend({
39385
+ healthy: booleanType(),
39386
+ status: arrayType(CliDiagnosticSchema)
39387
+ }).passthrough();
39388
+ var CliDoctorStoreSchema = objectType({
39389
+ id: stringType(),
39390
+ metadata: CliStoreMetadataSchema,
39391
+ origin_url: stringType().optional(),
39392
+ status: arrayType(CliDiagnosticSchema)
39393
+ }).passthrough();
39394
+ objectType({
39395
+ root: CliDoctorRootSchema.nullable(),
39396
+ store: CliDoctorStoreSchema.nullable(),
39397
+ references: arrayType(CliDoctorReferenceEntrySchema),
39398
+ status: arrayType(CliDiagnosticSchema)
39399
+ }).passthrough();
39400
+ var CliContextRootSchema = CliRootSchema.extend({ role: literalType("openspec_root") }).passthrough();
39401
+ var CliContextMemberSchema = objectType({
39402
+ role: literalType("referenced_store"),
39403
+ id: stringType(),
39404
+ path: stringType().optional(),
39405
+ remote: stringType().optional(),
39406
+ fetch: stringType().optional(),
39407
+ status: arrayType(CliDiagnosticSchema)
39408
+ }).passthrough();
39409
+ objectType({
39410
+ root: CliContextRootSchema.nullable(),
39411
+ members: arrayType(CliContextMemberSchema),
39412
+ status: arrayType(CliDiagnosticSchema)
39413
+ }).passthrough();
39414
+ unionType([
39415
+ CliStoreMutationSchema,
39416
+ CliStoreCleanupSchema,
39417
+ CliStoreListSchema,
39418
+ CliStoreDoctorSchema,
39419
+ CliDiagnosticFailureSchema
39420
+ ]);
39358
39421
  //#endregion
39359
39422
  //#region ../core/src/entity-id.ts
39360
39423
  var MAX_OPENSPEC_SPEC_ID_LENGTH = 4096;
@@ -46386,6 +46449,24 @@ var FileCode2 = createLucideIcon("FileCode2", [
46386
46449
  key: "112psh"
46387
46450
  }]
46388
46451
  ]);
46452
+ var FileDiff = createLucideIcon("FileDiff", [
46453
+ ["path", {
46454
+ d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",
46455
+ key: "1rqfz7"
46456
+ }],
46457
+ ["path", {
46458
+ d: "M9 10h6",
46459
+ key: "9gxzsh"
46460
+ }],
46461
+ ["path", {
46462
+ d: "M12 13V7",
46463
+ key: "h0r20n"
46464
+ }],
46465
+ ["path", {
46466
+ d: "M9 17h6",
46467
+ key: "r8uit2"
46468
+ }]
46469
+ ]);
46389
46470
  var FilePenLine = createLucideIcon("FilePenLine", [
46390
46471
  ["path", {
46391
46472
  d: "m18 5-2.414-2.414A2 2 0 0 0 14.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2",
@@ -71099,7 +71180,7 @@ var browserExt = {
71099
71180
  },
71100
71181
  test: () => true,
71101
71182
  load: async () => {
71102
- await import("./browserAll-BJZwRDaI.js");
71183
+ await import("./browserAll-ByxW2BCo.js");
71103
71184
  }
71104
71185
  };
71105
71186
  //#endregion
@@ -71112,7 +71193,7 @@ var webworkerExt = {
71112
71193
  },
71113
71194
  test: () => typeof self !== "undefined" && self.WorkerGlobalScope !== void 0,
71114
71195
  load: async () => {
71115
- await import("./webworkerAll-DVUDp5xO.js");
71196
+ await import("./webworkerAll-5v7Fs7LO.js");
71116
71197
  }
71117
71198
  };
71118
71199
  //#endregion
@@ -73706,7 +73787,7 @@ async function autoDetectRenderer(options) {
73706
73787
  for (let i = 0; i < preferredOrder.length; i++) {
73707
73788
  const rendererType = preferredOrder[i];
73708
73789
  if (rendererType === "webgpu" && await isWebGPUSupported()) {
73709
- const { WebGPURenderer } = await import("./WebGPURenderer-moX8CQUm.js");
73790
+ const { WebGPURenderer } = await import("./WebGPURenderer-D4vaKOO4.js");
73710
73791
  RendererClass = WebGPURenderer;
73711
73792
  finalOptions = {
73712
73793
  ...options,
@@ -73714,7 +73795,7 @@ async function autoDetectRenderer(options) {
73714
73795
  };
73715
73796
  break;
73716
73797
  } else if (rendererType === "webgl" && isWebGLSupported(options.failIfMajorPerformanceCaveat ?? AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat)) {
73717
- const { WebGLRenderer } = await import("./WebGLRenderer-cfN96M_D.js");
73798
+ const { WebGLRenderer } = await import("./WebGLRenderer-CLVKAqNO.js");
73718
73799
  RendererClass = WebGLRenderer;
73719
73800
  finalOptions = {
73720
73801
  ...options,
@@ -73722,7 +73803,7 @@ async function autoDetectRenderer(options) {
73722
73803
  };
73723
73804
  break;
73724
73805
  } else if (rendererType === "canvas") {
73725
- const { CanvasRenderer } = await import("./CanvasRenderer-k_tFIFoA.js");
73806
+ const { CanvasRenderer } = await import("./CanvasRenderer-D58O6peF.js");
73726
73807
  RendererClass = CanvasRenderer;
73727
73808
  finalOptions = {
73728
73809
  ...options,
@@ -97471,7 +97552,7 @@ var TerminalController = class {
97471
97552
  if (this.configPersistTimer) clearTimeout(this.configPersistTimer);
97472
97553
  this.configPersistTimer = setTimeout(() => {
97473
97554
  this.configPersistTimer = null;
97474
- import("./trpc-4dLqTVBm.js").then(({ trpcClient }) => {
97555
+ import("./trpc-BPMx2lHD.js").then(({ trpcClient }) => {
97475
97556
  trpcClient.config.update.mutate({ terminal: { fontSize: this.config.fontSize } });
97476
97557
  }).catch(() => {});
97477
97558
  }, CONFIG_PERSIST_DEBOUNCE);
@@ -108032,7 +108113,7 @@ var languages = [
108032
108113
  name: "CSS",
108033
108114
  extensions: ["css"],
108034
108115
  load() {
108035
- return import("./dist-CgFGYGuV.js").then((m) => m.css());
108116
+ return import("./dist-CiijDa1h.js").then((m) => m.css());
108036
108117
  }
108037
108118
  }),
108038
108119
  /* @__PURE__ */ LanguageDescription.of({
@@ -108052,7 +108133,7 @@ var languages = [
108052
108133
  "hbs"
108053
108134
  ],
108054
108135
  load() {
108055
- return import("./dist-C7cu-Ohs.js").then((m) => m.html());
108136
+ return import("./dist-BPIetWhy.js").then((m) => m.html());
108056
108137
  }
108057
108138
  }),
108058
108139
  /* @__PURE__ */ LanguageDescription.of({
@@ -108086,7 +108167,7 @@ var languages = [
108086
108167
  "jinja2"
108087
108168
  ],
108088
108169
  load() {
108089
- return import("./dist-CmkO24b2.js").then((m) => m.jinja());
108170
+ return import("./dist-Cj2NABFW.js").then((m) => m.jinja());
108090
108171
  }
108091
108172
  }),
108092
108173
  /* @__PURE__ */ LanguageDescription.of({
@@ -108094,7 +108175,7 @@ var languages = [
108094
108175
  alias: ["json5"],
108095
108176
  extensions: ["json", "map"],
108096
108177
  load() {
108097
- return import("./dist-Bosp3yvI.js").then((m) => m.json());
108178
+ return import("./dist-Ct3YhJiO.js").then((m) => m.json());
108098
108179
  }
108099
108180
  }),
108100
108181
  /* @__PURE__ */ LanguageDescription.of({
@@ -108108,14 +108189,14 @@ var languages = [
108108
108189
  name: "LESS",
108109
108190
  extensions: ["less"],
108110
108191
  load() {
108111
- return import("./dist-CTDTyhyq.js").then((m) => m.less());
108192
+ return import("./dist-DzYuWuV1.js").then((m) => m.less());
108112
108193
  }
108113
108194
  }),
108114
108195
  /* @__PURE__ */ LanguageDescription.of({
108115
108196
  name: "Liquid",
108116
108197
  extensions: ["liquid"],
108117
108198
  load() {
108118
- return import("./dist-FpVzh8vE.js").then((m) => m.liquid());
108199
+ return import("./dist-wEaYViHh.js").then((m) => m.liquid());
108119
108200
  }
108120
108201
  }),
108121
108202
  /* @__PURE__ */ LanguageDescription.of({
@@ -108132,7 +108213,7 @@ var languages = [
108132
108213
  "mkd"
108133
108214
  ],
108134
108215
  load() {
108135
- return import("./dist-BbKu_y6W.js").then((m) => m.markdown());
108216
+ return import("./dist-5xHpmSpA.js").then((m) => m.markdown());
108136
108217
  }
108137
108218
  }),
108138
108219
  /* @__PURE__ */ LanguageDescription.of({
@@ -108158,7 +108239,7 @@ var languages = [
108158
108239
  "phtml"
108159
108240
  ],
108160
108241
  load() {
108161
- return import("./dist-glvfDQXi.js").then((m) => m.php());
108242
+ return import("./dist-7sF3GmjJ.js").then((m) => m.php());
108162
108243
  }
108163
108244
  }),
108164
108245
  /* @__PURE__ */ LanguageDescription.of({
@@ -108198,14 +108279,14 @@ var languages = [
108198
108279
  name: "Sass",
108199
108280
  extensions: ["sass"],
108200
108281
  load() {
108201
- return import("./dist-Cxmy4PRF.js").then((m) => m.sass({ indented: true }));
108282
+ return import("./dist-C-7lPLui.js").then((m) => m.sass({ indented: true }));
108202
108283
  }
108203
108284
  }),
108204
108285
  /* @__PURE__ */ LanguageDescription.of({
108205
108286
  name: "SCSS",
108206
108287
  extensions: ["scss"],
108207
108288
  load() {
108208
- return import("./dist-Cxmy4PRF.js").then((m) => m.sass());
108289
+ return import("./dist-C-7lPLui.js").then((m) => m.sass());
108209
108290
  }
108210
108291
  }),
108211
108292
  /* @__PURE__ */ LanguageDescription.of({
@@ -108272,7 +108353,7 @@ var languages = [
108272
108353
  alias: ["yml"],
108273
108354
  extensions: ["yaml", "yml"],
108274
108355
  load() {
108275
- return import("./dist-DaxZJMDX.js").then((m) => m.yaml());
108356
+ return import("./dist-CkT7sc-T.js").then((m) => m.yaml());
108276
108357
  }
108277
108358
  }),
108278
108359
  /* @__PURE__ */ LanguageDescription.of({
@@ -109159,13 +109240,13 @@ var languages = [
109159
109240
  name: "Vue",
109160
109241
  extensions: ["vue"],
109161
109242
  load() {
109162
- return import("./dist-BZbvCEXY.js").then((m) => m.vue());
109243
+ return import("./dist-DvJqEVFD.js").then((m) => m.vue());
109163
109244
  }
109164
109245
  }),
109165
109246
  /* @__PURE__ */ LanguageDescription.of({
109166
109247
  name: "Angular Template",
109167
109248
  load() {
109168
- return import("./dist-C0TNMvo3.js").then((m) => m.angular());
109249
+ return import("./dist-j6yIDF4P.js").then((m) => m.angular());
109169
109250
  }
109170
109251
  })
109171
109252
  ];
@@ -171284,24 +171365,151 @@ function ApplyProgressNotice({ applyInstructionProgress }) {
171284
171365
  })]
171285
171366
  });
171286
171367
  }
171287
- var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.8", "1.9"];
171368
+ //#endregion
171369
+ //#region src/components/change-context-summary.tsx
171370
+ /**
171371
+ * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
171372
+ * 1. Project compact Schema, artifact progress, Root, Store, and Reference subtitle badges.
171373
+ * 2. Carry the Apply instruction count as one subtitle badge — the progress authority.
171374
+ * 3. Preserve current, retained, unavailable, and static authority distinctions.
171375
+ * 4. Keep Reference failures directly visible without owning subscriptions or mutations.
171376
+ *
171377
+ * Original request (2026-08-03): keep only necessary Change evidence in the default decision plane.
171378
+ * Owner correction (2026-08-03): unify Change scan Tooltips in the subtitle and keep failures below the Header.
171379
+ * Original request (2026-08-15): Owner walkthrough: merge Apply progress into the subtitle badge row.
171380
+ * Original request (2026-08-15): 刷新/解析中的 lifecycle 锁收敛为副标题行内的 shiny 徽章 + Tooltip。
171381
+ */
171382
+ function summarizeReferences(references) {
171383
+ return references.reduce((counts, reference) => {
171384
+ counts.total += reference.status.length;
171385
+ counts.errors += reference.status.filter((diagnostic) => diagnostic.severity === "error").length;
171386
+ counts.warnings += reference.status.filter((diagnostic) => diagnostic.severity === "warning").length;
171387
+ return counts;
171388
+ }, {
171389
+ errors: 0,
171390
+ warnings: 0,
171391
+ total: 0
171392
+ });
171393
+ }
171394
+ function referenceErrorLabels(references) {
171395
+ return references.flatMap((reference) => {
171396
+ const errors = reference.status.filter((diagnostic) => diagnostic.severity === "error").length;
171397
+ return errors > 0 ? [`${reference.store_id} (${errors})`] : [];
171398
+ });
171399
+ }
171400
+ /** Compact source-attributed facts that share the Change Header subtitle. */
171401
+ function ChangeContextSummary({ status, referenceEvidence, applyInstructionProgress, statusRefreshing = null, rootChecking = null }) {
171402
+ const provenance = status.provenance;
171403
+ const references = referenceEvidence.state === "unavailable" ? null : referenceEvidence.references;
171404
+ const referenceCounts = references ? summarizeReferences(references) : null;
171405
+ const doneCount = status.artifacts.filter((artifact) => artifact.status === "done").length;
171406
+ const totalCount = status.artifacts.length;
171407
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171408
+ "data-change-context-summary": "",
171409
+ "aria-label": "Change context summary",
171410
+ className: "flex min-w-0 flex-wrap items-center gap-1.5",
171411
+ children: [
171412
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171413
+ ariaLabel: `Workflow schema ${status.schemaName}`,
171414
+ tooltip: `OpenSpec workflow schema: ${status.schemaName}`,
171415
+ children: ["Schema: ", status.schemaName]
171416
+ }),
171417
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171418
+ ariaLabel: `Artifact progress ${doneCount} of ${totalCount}`,
171419
+ tooltip: `${doneCount} completed of ${totalCount} total artifacts.`,
171420
+ children: [
171421
+ doneCount,
171422
+ "/",
171423
+ totalCount,
171424
+ " artifacts"
171425
+ ]
171426
+ }),
171427
+ applyInstructionProgress ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApplyProgressBadge, { applyInstructionProgress }) : null,
171428
+ provenance.kind === "static" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171429
+ ariaLabel: "Static Change context has no live backend provenance",
171430
+ tooltip: "CLI Change context is unavailable in this static snapshot.",
171431
+ children: "Static snapshot"
171432
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171433
+ ariaLabel: `Change Root source ${provenance.root.source}${provenance.root.store_id ? `, Store ${provenance.root.store_id}` : ""}`,
171434
+ className: "max-w-full truncate",
171435
+ tooltip: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171436
+ className: "space-y-1",
171437
+ children: [
171438
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Change root: ", provenance.changeRoot] }),
171439
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Planning home: ", provenance.planningHome.root] }),
171440
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Root source: ", provenance.root.source] }),
171441
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Store: ", provenance.root.store_id ?? "none"] })
171442
+ ]
171443
+ }),
171444
+ children: provenance.root.store_id ? `Store ${provenance.root.store_id}` : provenance.root.source
171445
+ }),
171446
+ references && referenceCounts ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171447
+ ariaLabel: `${referenceEvidence.state === "retained" ? "Retained " : ""}${references.length} observed References, ${referenceCounts.errors} errors, ${referenceCounts.warnings} warnings`,
171448
+ tooltip: `${referenceEvidence.state === "retained" ? "Retained · " : ""}${references.length} References · ${referenceCounts.errors} errors · ${referenceCounts.warnings} warnings · ${referenceCounts.total} diagnostics`,
171449
+ tone: referenceCounts.errors > 0 ? "custom" : "muted",
171450
+ className: referenceCounts.errors > 0 ? "border-destructive/40 bg-destructive/10 text-destructive" : void 0,
171451
+ children: [
171452
+ referenceEvidence.state === "retained" ? "Retained " : "",
171453
+ "References ",
171454
+ references.length
171455
+ ]
171456
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171457
+ ariaLabel: "Reference evidence unavailable",
171458
+ tooltip: referenceEvidence.state === "unavailable" && referenceEvidence.reason === "static" ? "Reference evidence is not published in this static snapshot." : "Reference evidence is unavailable until Root Context is observed.",
171459
+ children: "References unavailable"
171460
+ }),
171461
+ rootChecking ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShinyStatusBadge, {
171462
+ label: rootChecking.label,
171463
+ message: rootChecking.message
171464
+ }) : null,
171465
+ statusRefreshing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShinyStatusBadge, {
171466
+ label: statusRefreshing.label,
171467
+ message: statusRefreshing.message
171468
+ }) : null
171469
+ ]
171470
+ });
171471
+ }
171472
+ /** Direct Reference failures stay below the Header instead of expanding the subtitle badge row. */
171473
+ function ChangeReferenceFailureNotice({ referenceEvidence }) {
171474
+ const referenceErrors = referenceEvidence.state === "unavailable" ? [] : referenceErrorLabels(referenceEvidence.references);
171475
+ if (referenceErrors.length === 0) return null;
171476
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171477
+ className: "text-destructive flex items-start gap-2 text-xs",
171478
+ role: "alert",
171479
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleAlert, {
171480
+ className: "mt-0.5 h-3.5 w-3.5 shrink-0",
171481
+ "aria-hidden": true
171482
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["Reference errors: ", referenceErrors.join(", ")] })]
171483
+ });
171484
+ }
171485
+ //#endregion
171486
+ //#region ../core/src/openspec-compat.ts
171487
+ var OPENSPEC_CLI_TARGET_SERIES = "1.11";
171488
+ var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.10", "1.11"];
171489
+ var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.10.0 <1.12.0";
171288
171490
  /**
171289
171491
  * Derive command capabilities from one parsed CLI version.
171290
171492
  *
171291
171493
  * Only an admitted version — stable inside the accepted range — can select version-specific
171292
- * capabilities. Unsupported forms (prereleases, >=1.10, below-range) and unparseable output
171494
+ * capabilities. Unsupported forms (prereleases, >=1.12, below-range) and unparseable output
171293
171495
  * keep their mismatch evidence and expose no capability, so a page-level version bypass can
171294
- * never manufacture a 1.9 command surface for a CLI the release line does not admit.
171496
+ * never manufacture a 1.11 command surface for a CLI the release line does not admit.
171295
171497
  */
171296
171498
  function deriveOpenSpecCliCapabilities(version) {
171297
171499
  if (!isAdmittedVersion(version)) return {
171298
171500
  schemasRootSelector: false,
171299
- archivedValidation: false
171501
+ archivedValidation: false,
171502
+ initLanguage: false,
171503
+ batchStatus: false,
171504
+ requirementDiff: false
171300
171505
  };
171301
- const onTargetSeries = isSeries(version, "1.9");
171506
+ const onTargetSeries = isSeries(version, OPENSPEC_CLI_TARGET_SERIES);
171302
171507
  return {
171303
- schemasRootSelector: onTargetSeries,
171304
- archivedValidation: onTargetSeries
171508
+ schemasRootSelector: true,
171509
+ archivedValidation: true,
171510
+ initLanguage: true,
171511
+ batchStatus: onTargetSeries,
171512
+ requirementDiff: onTargetSeries
171305
171513
  };
171306
171514
  }
171307
171515
  function parseOpenSpecCliVersion(raw) {
@@ -171325,22 +171533,28 @@ function isStable(version) {
171325
171533
  /** True only for stable versions inside the accepted range (current or supported non-current). */
171326
171534
  function isAdmittedVersion(version) {
171327
171535
  if (!version || !isStable(version)) return false;
171328
- return isSeries(version, "1.9") || isSupportedNonCurrentSeries(version);
171536
+ return isSeries(version, "1.11") || isSupportedNonCurrentSeries(version);
171329
171537
  }
171330
171538
  function isSupportedNonCurrentSeries(version) {
171331
- return OPENSPEC_CLI_SUPPORTED_SERIES.filter((series) => series !== "1.9").some((series) => isSeries(version, series));
171539
+ return OPENSPEC_CLI_SUPPORTED_SERIES.filter((series) => series !== OPENSPEC_CLI_TARGET_SERIES).some((series) => isSeries(version, series));
171332
171540
  }
171333
171541
  //#endregion
171334
171542
  //#region src/components/archived-validation-evidence.tsx
171335
171543
  /**
171336
- * Orthogonal intents (created 2026-08-15 Asia/Shanghai):
171337
- * 1. Present OpenSpec 1.9 `validate --archived --json` as typed CLI evidence.
171544
+ * Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
171545
+ * 1. Present OpenSpec `validate --archived --json` as typed CLI evidence.
171338
171546
  * 2. Preserve item issues, totals, root, and exit/failure evidence without repair actions.
171339
171547
  * 3. Identify the evidence as unavailable in static snapshots instead of fabricating it.
171340
- * 4. Derive the capability from the detected admitted CLI and hide the action on 1.8.
171548
+ * 4. Derive the capability from the detected admitted CLI; both admitted v11 lines (1.10 and
171549
+ * 1.11) declare it, so the unavailable branch names the accepted range, not one series.
171341
171550
  * 5. Validate report payloads with the Core contract schema, never shallow shape guards.
171551
+ * 6. Mount directly inside the Evidence workspace detail pane: the Accordion shell is gone, the
171552
+ * section header keeps the title and summary facts, and `onChip` reports only derived facts
171553
+ * (pass/fail from the typed report, typed unavailable) for the workspace rows.
171342
171554
  *
171343
171555
  * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
171556
+ * Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
171557
+ * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
171344
171558
  */
171345
171559
  function parseValidationReport(value) {
171346
171560
  const parsed = CliValidateReportSchema.safeParse(value);
@@ -171388,28 +171602,89 @@ function RunButton({ pending, label, onRun }) {
171388
171602
  }), label]
171389
171603
  });
171390
171604
  }
171391
- /** On-demand, read-only archived-task validation evidence for the Change Evidence tab. */
171392
- function ArchivedValidationEvidence() {
171605
+ /**
171606
+ * Structure-agnostic section frame for the Evidence workspace detail pane. The heading and
171607
+ * summary line preserve the facts the former Accordion trigger carried; the content is
171608
+ * presented directly — the workspace, not a disclosure, owns reveal behavior.
171609
+ */
171610
+ function ArchivedValidationSection({ summary, children }) {
171611
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
171612
+ "data-evidence-section": "archived-validation",
171613
+ "aria-label": "Archived validation",
171614
+ className: "min-w-0",
171615
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
171616
+ className: "border-border/60 flex min-w-0 flex-wrap items-baseline justify-between gap-x-3 gap-y-1 border-b pb-2",
171617
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
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
+ })]
171624
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171625
+ className: "min-w-0 pt-3",
171626
+ children
171627
+ })]
171628
+ });
171629
+ }
171630
+ /** On-demand, read-only archived-task validation evidence for the Change Evidence workspace. */
171631
+ function ArchivedValidationEvidence({ onChip } = {}) {
171393
171632
  const [report, setReport] = (0, import_react.useState)(null);
171394
171633
  const [error, setError] = (0, import_react.useState)(null);
171395
171634
  const [pending, setPending] = (0, import_react.useState)(false);
171396
171635
  const cli = useRootActionState().context?.cli;
171636
+ const staticMode = isStaticMode();
171397
171637
  const capabilities = deriveOpenSpecCliCapabilities(cli?.available ? parseOpenSpecCliVersion(cli.version) : null);
171398
- if (isStaticMode()) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171399
- title: "Archived validation",
171638
+ const chip = (0, import_react.useMemo)(() => {
171639
+ if (staticMode) return {
171640
+ label: "unavailable",
171641
+ tone: "unavailable"
171642
+ };
171643
+ if (cli?.available === true && !capabilities.archivedValidation) return {
171644
+ label: "unavailable",
171645
+ tone: "unavailable"
171646
+ };
171647
+ if (!report && !error) return null;
171648
+ const parsed = report ? parseValidationReport(report.data) : {
171649
+ report: null,
171650
+ schemaIssues: []
171651
+ };
171652
+ if (error || !parsed.report) return {
171653
+ label: "fail",
171654
+ tone: "negative"
171655
+ };
171656
+ return parsed.report.summary.totals.failed > 0 ? {
171657
+ label: "fail",
171658
+ tone: "negative"
171659
+ } : {
171660
+ label: "pass",
171661
+ tone: "positive"
171662
+ };
171663
+ }, [
171664
+ capabilities.archivedValidation,
171665
+ cli?.available,
171666
+ error,
171667
+ report,
171668
+ staticMode
171669
+ ]);
171670
+ (0, import_react.useEffect)(() => {
171671
+ onChip?.(chip);
171672
+ }, [chip, onChip]);
171673
+ if (staticMode) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationSection, {
171400
171674
  summary: "Unavailable in static snapshot",
171401
171675
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
171402
171676
  className: "text-muted-foreground",
171403
171677
  children: "Archived-task validation is live CLI evidence and is not captured in this static snapshot."
171404
171678
  })
171405
171679
  });
171406
- if (cli?.available === true && !capabilities.archivedValidation) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171407
- title: "Archived validation",
171680
+ if (cli?.available === true && !capabilities.archivedValidation) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationSection, {
171408
171681
  summary: "Unavailable on this CLI line",
171409
171682
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
171410
171683
  className: "text-muted-foreground",
171411
171684
  children: [
171412
- "Archived-task validation requires the OpenSpec 1.9 line",
171685
+ "Archived-task validation requires an admitted OpenSpec CLI line (",
171686
+ OPENSPEC_CLI_ACCEPTED_RANGE,
171687
+ ")",
171413
171688
  cli.version ? ` (detected ${cli.version.trim()})` : "",
171414
171689
  ". This session's CLI does not declare the capability, so no command is offered."
171415
171690
  ]
@@ -171434,9 +171709,8 @@ function ArchivedValidationEvidence() {
171434
171709
  setPending(false);
171435
171710
  }
171436
171711
  };
171437
- if (!report && !error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171438
- title: "Archived validation",
171439
- summary: "OpenSpec 1.9 archived-task validation",
171712
+ if (!report && !error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationSection, {
171713
+ summary: "OpenSpec archived-task validation",
171440
171714
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171441
171715
  className: "space-y-2",
171442
171716
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
@@ -171456,8 +171730,7 @@ function ArchivedValidationEvidence() {
171456
171730
  const validationReport = parsed.report;
171457
171731
  if (error || !validationReport) {
171458
171732
  const schemaDiagnostic = parsed.schemaIssues.length > 0 ? parsed.schemaIssues.join("; ") : null;
171459
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171460
- title: "Archived validation",
171733
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationSection, {
171461
171734
  summary: "CLI failure evidence",
171462
171735
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171463
171736
  className: "space-y-2",
@@ -171481,8 +171754,7 @@ function ArchivedValidationEvidence() {
171481
171754
  }
171482
171755
  const validation = validationReport;
171483
171756
  const failed = validation.summary.totals.failed;
171484
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171485
- title: "Archived validation",
171757
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationSection, {
171486
171758
  summary: `${validation.summary.totals.passed} passed · ${failed} failed`,
171487
171759
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171488
171760
  className: "space-y-3",
@@ -171550,143 +171822,365 @@ function ArchivedValidationEvidence() {
171550
171822
  });
171551
171823
  }
171552
171824
  //#endregion
171553
- //#region src/components/change-context-summary.tsx
171554
- /**
171555
- * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
171556
- * 1. Project compact Schema, artifact progress, Root, Store, and Reference subtitle badges.
171557
- * 2. Carry the Apply instruction count as one subtitle badge — the progress authority.
171558
- * 3. Preserve current, retained, unavailable, and static authority distinctions.
171559
- * 4. Keep Reference failures directly visible without owning subscriptions or mutations.
171560
- *
171561
- * Original request (2026-08-03): keep only necessary Change evidence in the default decision plane.
171562
- * Owner correction (2026-08-03): unify Change scan Tooltips in the subtitle and keep failures below the Header.
171563
- * Original request (2026-08-15): Owner walkthrough: merge Apply progress into the subtitle badge row.
171564
- * Original request (2026-08-15): 刷新/解析中的 lifecycle 锁收敛为副标题行内的 shiny 徽章 + Tooltip。
171565
- */
171566
- function summarizeReferences(references) {
171567
- return references.reduce((counts, reference) => {
171568
- counts.total += reference.status.length;
171569
- counts.errors += reference.status.filter((diagnostic) => diagnostic.severity === "error").length;
171570
- counts.warnings += reference.status.filter((diagnostic) => diagnostic.severity === "warning").length;
171571
- return counts;
171572
- }, {
171573
- errors: 0,
171574
- warnings: 0,
171575
- total: 0
171825
+ //#region src/components/change-diff-evidence.tsx
171826
+ /**
171827
+ * Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
171828
+ * 1. Present the CLI-provided MODIFIED-delta `diff`/`warning` fields as Change Detail evidence.
171829
+ * 2. Color the unified diff body by line role (+/-/@@) without recomputing anything locally.
171830
+ * 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 (1.11 only) and on
171832
+ * live mode: static snapshots and 1.10 sessions never issue the transport call.
171833
+ * 5. Degrade to the existing delta presentation when the fields are absent — no fabricated diff
171834
+ * or warning may appear.
171835
+ * 6. Mount directly inside the Evidence workspace detail pane: the Accordion shell is gone, the
171836
+ * section header keeps the title and summary facts, and `onChip` reports only derived facts
171837
+ * (CLI MODIFIED-delta count, typed unavailable, transport failure) for the workspace rows.
171838
+ *
171839
+ * Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
171840
+ * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
171841
+ */
171842
+ function diffLineRole(line) {
171843
+ if (line.startsWith("@@")) return "hunk";
171844
+ if (line.startsWith("+")) return "add";
171845
+ if (line.startsWith("-")) return "remove";
171846
+ return "context";
171847
+ }
171848
+ var DIFF_LINE_CLASS = {
171849
+ hunk: "text-sky-700 bg-sky-500/5 dark:text-sky-300",
171850
+ add: "text-emerald-700 bg-emerald-500/10 dark:text-emerald-300",
171851
+ remove: "text-rose-700 bg-rose-500/10 dark:text-rose-300",
171852
+ context: "text-muted-foreground"
171853
+ };
171854
+ /** One unified diff body rendered line-by-line; wrapped so no path forces horizontal overflow. */
171855
+ function DiffBody({ diff }) {
171856
+ const lines = diff.split("\n");
171857
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", {
171858
+ "data-diff-body": true,
171859
+ "aria-label": "Requirement diff",
171860
+ className: "bg-muted/30 max-h-72 max-w-full overflow-y-auto rounded p-2 font-mono text-[11px] leading-relaxed",
171861
+ children: lines.map((line, index) => {
171862
+ const role = diffLineRole(line);
171863
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171864
+ "data-diff-line": role,
171865
+ className: `whitespace-pre-wrap break-all ${DIFF_LINE_CLASS[role]}`,
171866
+ children: line === "" ? "\xA0" : line
171867
+ }, index);
171868
+ })
171576
171869
  });
171577
171870
  }
171578
- function referenceErrorLabels(references) {
171579
- return references.flatMap((reference) => {
171580
- const errors = reference.status.filter((diagnostic) => diagnostic.severity === "error").length;
171581
- return errors > 0 ? [`${reference.store_id} (${errors})`] : [];
171871
+ function DeltaWarning({ warning }) {
171872
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171873
+ "data-diff-warning": true,
171874
+ role: "note",
171875
+ className: "flex items-start gap-2 rounded-md border border-amber-400/50 bg-amber-500/10 p-2 text-amber-800 dark:text-amber-300",
171876
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
171877
+ className: "mt-0.5 h-3.5 w-3.5 shrink-0",
171878
+ "aria-hidden": true
171879
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
171880
+ className: "min-w-0 whitespace-pre-wrap break-words",
171881
+ children: warning
171882
+ })]
171582
171883
  });
171583
171884
  }
171584
- /** Compact source-attributed facts that share the Change Header subtitle. */
171585
- function ChangeContextSummary({ status, referenceEvidence, applyInstructionProgress, statusRefreshing = null, rootChecking = null }) {
171586
- const provenance = status.provenance;
171587
- const references = referenceEvidence.state === "unavailable" ? null : referenceEvidence.references;
171588
- const referenceCounts = references ? summarizeReferences(references) : null;
171589
- const doneCount = status.artifacts.filter((artifact) => artifact.status === "done").length;
171590
- const totalCount = status.artifacts.length;
171591
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171592
- "data-change-context-summary": "",
171593
- "aria-label": "Change context summary",
171594
- className: "flex min-w-0 flex-wrap items-center gap-1.5",
171885
+ /** Compact operation badge mirroring the delta vocabulary of the Change surfaces. */
171886
+ function OperationBadge({ operation }) {
171887
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
171888
+ className: `rounded px-1.5 py-0.5 text-[10px] font-medium ${operation === "MODIFIED" ? "border border-amber-200 bg-amber-100 text-amber-800" : operation === "ADDED" ? "border border-emerald-200 bg-emerald-100 text-emerald-700" : operation === "REMOVED" ? "border border-rose-200 bg-rose-100 text-rose-700" : "border border-sky-200 bg-sky-100 text-sky-700"}`,
171889
+ children: operation
171890
+ });
171891
+ }
171892
+ function DiffProvenance({ provenance }) {
171893
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
171894
+ "data-diff-provenance": true,
171895
+ className: "@[32rem]:grid-cols-[auto_minmax(0,1fr)] grid min-w-0 gap-x-3 gap-y-1",
171595
171896
  children: [
171596
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171597
- ariaLabel: `Workflow schema ${status.schemaName}`,
171598
- tooltip: `OpenSpec workflow schema: ${status.schemaName}`,
171599
- children: ["Schema: ", status.schemaName]
171897
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
171898
+ className: "text-muted-foreground",
171899
+ children: "Command"
171600
171900
  }),
171601
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171602
- ariaLabel: `Artifact progress ${doneCount} of ${totalCount}`,
171603
- tooltip: `${doneCount} completed of ${totalCount} total artifacts.`,
171604
- children: [
171605
- doneCount,
171606
- "/",
171607
- totalCount,
171608
- " artifacts"
171609
- ]
171901
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
171902
+ className: "min-w-0 break-all font-mono",
171903
+ children: provenance.command
171610
171904
  }),
171611
- applyInstructionProgress ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApplyProgressBadge, { applyInstructionProgress }) : null,
171612
- provenance.kind === "static" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171613
- ariaLabel: "Static Change context has no live backend provenance",
171614
- tooltip: "CLI Change context is unavailable in this static snapshot.",
171615
- children: "Static snapshot"
171616
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171617
- ariaLabel: `Change Root source ${provenance.root.source}${provenance.root.store_id ? `, Store ${provenance.root.store_id}` : ""}`,
171618
- className: "max-w-full truncate",
171619
- tooltip: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171620
- className: "space-y-1",
171621
- children: [
171622
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Change root: ", provenance.changeRoot] }),
171623
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Planning home: ", provenance.planningHome.root] }),
171624
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Root source: ", provenance.root.source] }),
171625
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: ["Store: ", provenance.root.store_id ?? "none"] })
171626
- ]
171627
- }),
171628
- children: provenance.root.store_id ? `Store ${provenance.root.store_id}` : provenance.root.source
171905
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
171906
+ className: "text-muted-foreground",
171907
+ children: "Root"
171629
171908
  }),
171630
- references && referenceCounts ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171631
- ariaLabel: `${referenceEvidence.state === "retained" ? "Retained " : ""}${references.length} observed References, ${referenceCounts.errors} errors, ${referenceCounts.warnings} warnings`,
171632
- tooltip: `${referenceEvidence.state === "retained" ? "Retained · " : ""}${references.length} References · ${referenceCounts.errors} errors · ${referenceCounts.warnings} warnings · ${referenceCounts.total} diagnostics`,
171633
- tone: referenceCounts.errors > 0 ? "custom" : "muted",
171634
- className: referenceCounts.errors > 0 ? "border-destructive/40 bg-destructive/10 text-destructive" : void 0,
171635
- children: [
171636
- referenceEvidence.state === "retained" ? "Retained " : "",
171637
- "References ",
171638
- references.length
171639
- ]
171640
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InformationBadge, {
171641
- ariaLabel: "Reference evidence unavailable",
171642
- tooltip: referenceEvidence.state === "unavailable" && referenceEvidence.reason === "static" ? "Reference evidence is not published in this static snapshot." : "Reference evidence is unavailable until Root Context is observed.",
171643
- children: "References unavailable"
171909
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
171910
+ className: "min-w-0 break-all font-mono",
171911
+ children: provenance.root
171644
171912
  }),
171645
- rootChecking ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShinyStatusBadge, {
171646
- label: rootChecking.label,
171647
- message: rootChecking.message
171648
- }) : null,
171649
- statusRefreshing ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShinyStatusBadge, {
171650
- label: statusRefreshing.label,
171651
- message: statusRefreshing.message
171652
- }) : null
171913
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
171914
+ className: "text-muted-foreground",
171915
+ children: "Exit"
171916
+ }),
171917
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: provenance.exitCode ?? "unknown" })
171653
171918
  ]
171654
171919
  });
171655
171920
  }
171656
- /** Direct Reference failures stay below the Header instead of expanding the subtitle badge row. */
171657
- function ChangeReferenceFailureNotice({ referenceEvidence }) {
171658
- const referenceErrors = referenceEvidence.state === "unavailable" ? [] : referenceErrorLabels(referenceEvidence.references);
171659
- if (referenceErrors.length === 0) return null;
171660
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171661
- className: "text-destructive flex items-start gap-2 text-xs",
171662
- role: "alert",
171663
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleAlert, {
171664
- className: "mt-0.5 h-3.5 w-3.5 shrink-0",
171665
- "aria-hidden": true
171666
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: ["Reference errors: ", referenceErrors.join(", ")] })]
171921
+ /**
171922
+ * Structure-agnostic section frame for the Evidence workspace detail pane. The heading and
171923
+ * summary line preserve the facts the former Accordion trigger carried; the content is
171924
+ * presented directly — the workspace, not a disclosure, owns reveal behavior.
171925
+ */
171926
+ function RequirementDiffsSection({ summary, children }) {
171927
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
171928
+ "data-evidence-section": "requirement-diffs",
171929
+ "aria-label": "Requirement diffs",
171930
+ className: "min-w-0",
171931
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
171932
+ className: "border-border/60 flex min-w-0 flex-wrap items-baseline justify-between gap-x-3 gap-y-1 border-b pb-2",
171933
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
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
+ })]
171940
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171941
+ className: "min-w-0 pt-3",
171942
+ children
171943
+ })]
171944
+ });
171945
+ }
171946
+ /** CLI MODIFIED-delta diff evidence for the Change Evidence workspace (live 1.11 sessions only). */
171947
+ function ChangeDiffEvidence({ changeId, onChip }) {
171948
+ const cli = useRootActionState().context?.cli;
171949
+ const diffCapable = deriveOpenSpecCliCapabilities(cli?.available ? parseOpenSpecCliVersion(cli.version) : null).requirementDiff;
171950
+ const staticMode = isStaticMode();
171951
+ const [evidence, setEvidence] = (0, import_react.useState)(null);
171952
+ const [error, setError] = (0, import_react.useState)(null);
171953
+ const [pending, setPending] = (0, import_react.useState)(false);
171954
+ (0, import_react.useEffect)(() => {
171955
+ if (staticMode || !diffCapable) return;
171956
+ let cancelled = false;
171957
+ setPending(true);
171958
+ setError(null);
171959
+ setEvidence(null);
171960
+ trpcClient.change.diffEvidence.query({ id: changeId }).then((result) => {
171961
+ if (!cancelled) setEvidence(result);
171962
+ }).catch((cause) => {
171963
+ if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause));
171964
+ }).finally(() => {
171965
+ if (!cancelled) setPending(false);
171966
+ });
171967
+ return () => {
171968
+ cancelled = true;
171969
+ };
171970
+ }, [
171971
+ changeId,
171972
+ diffCapable,
171973
+ staticMode
171974
+ ]);
171975
+ const chip = (0, import_react.useMemo)(() => {
171976
+ if (staticMode) return {
171977
+ label: "unavailable",
171978
+ tone: "unavailable"
171979
+ };
171980
+ if (!diffCapable) {
171981
+ if (cli?.available !== true) return null;
171982
+ return {
171983
+ label: "unavailable",
171984
+ tone: "unavailable"
171985
+ };
171986
+ }
171987
+ if (error) return {
171988
+ label: "error",
171989
+ tone: "error"
171990
+ };
171991
+ if (!evidence) return null;
171992
+ if (evidence.kind !== "executed") return {
171993
+ label: "unavailable",
171994
+ tone: "unavailable"
171995
+ };
171996
+ return {
171997
+ label: `${evidence.deltas.filter((delta) => delta.operation === "MODIFIED").length} MODIFIED`,
171998
+ tone: "neutral"
171999
+ };
172000
+ }, [
172001
+ cli?.available,
172002
+ diffCapable,
172003
+ error,
172004
+ evidence,
172005
+ staticMode
172006
+ ]);
172007
+ (0, import_react.useEffect)(() => {
172008
+ onChip?.(chip);
172009
+ }, [chip, onChip]);
172010
+ if (staticMode) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172011
+ summary: "Unavailable in static snapshot",
172012
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
172013
+ className: "text-muted-foreground",
172014
+ children: "Requirement diffs are live CLI evidence from `show --diff` and are not captured in this static snapshot. The delta content shown on this page remains the captured local presentation."
172015
+ })
172016
+ });
172017
+ if (!diffCapable) {
172018
+ if (cli?.available !== true) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172019
+ summary: "CLI diff evidence",
172020
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
172021
+ className: "text-muted-foreground",
172022
+ children: "Requirement diff evidence from `show --diff` appears here on admitted OpenSpec CLI 1.11 sessions once the CLI is detected."
172023
+ })
172024
+ });
172025
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172026
+ summary: "Unavailable on this CLI line",
172027
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
172028
+ className: "text-muted-foreground",
172029
+ children: [
172030
+ "Requirement diffs require an admitted OpenSpec CLI 1.11 session",
172031
+ cli.version ? ` (detected ${cli.version.trim()})` : "",
172032
+ ". This session's CLI does not declare the `show --diff` capability, so the delta presentation keeps using the captured local content."
172033
+ ]
172034
+ })
172035
+ });
172036
+ }
172037
+ if (pending && !evidence && !error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172038
+ summary: "Loading CLI diff evidence",
172039
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
172040
+ className: "text-muted-foreground flex items-center gap-2",
172041
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(LoaderCircle, {
172042
+ className: "h-3.5 w-3.5 animate-spin",
172043
+ "aria-hidden": true
172044
+ }), "Fetching `show --diff` evidence from the official CLI…"]
172045
+ })
172046
+ });
172047
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172048
+ summary: "Transport failure",
172049
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172050
+ className: "text-destructive flex items-start gap-2 break-words",
172051
+ role: "alert",
172052
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
172053
+ className: "mt-0.5 h-3.5 w-3.5 shrink-0",
172054
+ "aria-hidden": true
172055
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
172056
+ className: "min-w-0 break-all",
172057
+ children: error
172058
+ })]
172059
+ })
172060
+ });
172061
+ if (!evidence) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172062
+ summary: "CLI diff evidence",
172063
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
172064
+ className: "text-muted-foreground",
172065
+ children: "Requirement diff evidence from `show --diff` appears here on 1.11 sessions."
172066
+ })
172067
+ });
172068
+ if (evidence.kind !== "executed") {
172069
+ const detail = evidence.reason === "command-failed" ? evidence.detail : evidence.reason === "capability" ? "The detected OpenSpec CLI does not declare the 1.11 requirement-diff capability." : "The planning root is unavailable, so requirement-diff evidence cannot be fetched.";
172070
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172071
+ summary: "CLI evidence unavailable",
172072
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172073
+ className: "space-y-1",
172074
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
172075
+ className: "text-muted-foreground",
172076
+ children: "Requirement diffs are unavailable for this session. The delta presentation keeps using the captured local content."
172077
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
172078
+ className: "break-words",
172079
+ "data-diff-unavailable-detail": true,
172080
+ children: detail
172081
+ })]
172082
+ })
172083
+ });
172084
+ }
172085
+ const modifiedDeltas = evidence.deltas.filter((delta) => delta.operation === "MODIFIED" && (delta.diff !== null || delta.warning !== null));
172086
+ const modifiedCount = evidence.deltas.filter((delta) => delta.operation === "MODIFIED").length;
172087
+ if (modifiedDeltas.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172088
+ summary: `${modifiedCount} MODIFIED · CLI provided no diff fields`,
172089
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172090
+ className: "min-w-0 space-y-3",
172091
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
172092
+ className: "text-muted-foreground",
172093
+ children: [
172094
+ "The CLI reported ",
172095
+ modifiedCount,
172096
+ " MODIFIED ",
172097
+ modifiedCount === 1 ? "delta" : "deltas",
172098
+ " ",
172099
+ "with no requirement-diff fields. No diff is fabricated locally."
172100
+ ]
172101
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffProvenance, { provenance: evidence.provenance })]
172102
+ })
172103
+ });
172104
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementDiffsSection, {
172105
+ summary: `${modifiedCount} MODIFIED · CLI show --diff`,
172106
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172107
+ className: "min-w-0 space-y-3",
172108
+ children: [
172109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
172110
+ className: "text-muted-foreground flex items-center gap-1.5",
172111
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileDiff, {
172112
+ className: "h-3.5 w-3.5 shrink-0",
172113
+ "aria-hidden": true
172114
+ }), "CLI-owned `show --diff` evidence; never recomputed locally."]
172115
+ }),
172116
+ evidence.deltas.map((delta, index) => {
172117
+ if (delta.operation !== "MODIFIED") return null;
172118
+ if (delta.diff === null && delta.warning === null) return null;
172119
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172120
+ "data-diff-delta": delta.spec,
172121
+ className: "border-border/60 space-y-2 rounded border p-2",
172122
+ children: [
172123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172124
+ className: "flex min-w-0 items-center gap-2",
172125
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
172126
+ className: "min-w-0 break-all font-mono text-[11px]",
172127
+ children: delta.spec
172128
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OperationBadge, { operation: delta.operation })]
172129
+ }),
172130
+ delta.warning !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeltaWarning, { warning: delta.warning }) : null,
172131
+ delta.diff !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffBody, { diff: delta.diff }) : null
172132
+ ]
172133
+ }, `${delta.spec}:${index}`);
172134
+ }),
172135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DiffProvenance, { provenance: evidence.provenance })
172136
+ ]
172137
+ })
171667
172138
  });
171668
172139
  }
171669
172140
  //#endregion
171670
172141
  //#region src/components/change-evidence-panel.tsx
171671
172142
  /**
171672
- * Orthogonal intents (created 2026-08-03 Asia/Shanghai):
172143
+ * Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
171673
172144
  * 1. Render complete source-attributed Change paths, action context, and CLI evidence.
171674
- * 2. Preserve layered Artifact, Reference, CLI-result, and raw-payload disclosure.
171675
- * 3. Own bounded Evidence-tab scrolling and explicit static/unavailable presentation.
172145
+ * 2. Expose the former stacked panel as two list-addressable Evidence workspace sections:
172146
+ * summary/paths first and CLI result (with the raw payload disclosure) last.
172147
+ * 3. Preserve layered Artifact, Reference, CLI-result, and raw-payload disclosure and the
172148
+ * explicit static/unavailable presentation; the workspace detail pane owns scrolling.
171676
172149
  *
171677
172150
  * Original request (2026-08-03): use an Evidence tab to carry complete Change Detail information.
172151
+ * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
171678
172152
  */
171679
- /** Complete read-only evidence panel rendered inside the Change Evidence tab. */
171680
- function ChangeEvidencePanel({ status, referenceEvidence }) {
172153
+ /** Shared section frame for the Evidence workspace detail pane; keeps the a11y heading. */
172154
+ function WorkspaceSection({ id, title, summary, children, container = false }) {
172155
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
172156
+ "data-evidence-section": id,
172157
+ "aria-label": title,
172158
+ className: container ? "@container min-w-0" : "min-w-0",
172159
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
172160
+ className: "border-border/60 flex min-w-0 flex-wrap items-baseline justify-between gap-x-3 gap-y-1 border-b pb-2",
172161
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
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]
172168
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
172169
+ className: "min-w-0 pt-3 text-xs",
172170
+ children
172171
+ })]
172172
+ });
172173
+ }
172174
+ /** Readable paths/facts plus the layered Artifact and Reference disclosures (first row). */
172175
+ function ChangeSummaryPathsSection({ status, referenceEvidence }) {
171681
172176
  const provenance = status.provenance;
171682
172177
  if (provenance.kind === "static") {
171683
172178
  const artifactCount = status.artifacts.length;
171684
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", {
171685
- "data-change-evidence-scroll-owner": "",
171686
- "aria-label": "Change Evidence",
171687
- className: "scrollbar-thin scrollbar-track-transparent flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto overflow-x-hidden overscroll-contain p-4",
172179
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceSection, {
172180
+ id: "summary-paths",
172181
+ title: "Summary & paths",
171688
172182
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171689
- className: "min-w-0 space-y-3 p-4 text-xs",
172183
+ className: "space-y-3",
171690
172184
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171691
172185
  className: "border-border bg-muted/20 text-muted-foreground rounded-md border p-4 text-sm",
171692
172186
  children: "CLI Change context and Reference evidence are unavailable in this static snapshot."
@@ -171699,12 +172193,12 @@ function ChangeEvidencePanel({ status, referenceEvidence }) {
171699
172193
  });
171700
172194
  }
171701
172195
  const artifactCount = Object.keys(provenance.artifactPaths).length;
171702
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", {
171703
- "data-change-evidence-scroll-owner": "",
171704
- "aria-label": "Change Evidence",
171705
- className: "scrollbar-thin scrollbar-track-transparent flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto overflow-x-hidden overscroll-contain",
172196
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceSection, {
172197
+ id: "summary-paths",
172198
+ title: "Summary & paths",
172199
+ container: true,
171706
172200
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171707
- className: "@container min-w-0 space-y-3 p-4 text-xs",
172201
+ className: "min-w-0 space-y-3",
171708
172202
  children: [
171709
172203
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReadableChangeFacts, { provenance }),
171710
172204
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
@@ -171741,16 +172235,22 @@ function ChangeEvidencePanel({ status, referenceEvidence }) {
171741
172235
  title: "References",
171742
172236
  summary: referenceSummary(referenceEvidence),
171743
172237
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReferenceEvidence$1, { evidence: referenceEvidence })
171744
- }),
171745
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceDisclosure, {
171746
- title: "CLI result",
171747
- summary: `${provenance.evidence.command} · exit ${provenance.evidence.exitCode ?? "unknown"}`,
171748
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CliResultEvidence, { evidence: provenance.evidence })
171749
172238
  })
171750
172239
  ]
171751
172240
  })
171752
172241
  });
171753
172242
  }
172243
+ /** CLI result with the raw payload disclosure (last row; live CLI provenance only). */
172244
+ function ChangeCliResultSection({ status }) {
172245
+ if (status.provenance.kind === "static") return null;
172246
+ const provenance = status.provenance;
172247
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkspaceSection, {
172248
+ id: "cli-result",
172249
+ title: "CLI result",
172250
+ summary: `${provenance.evidence.command} · exit ${provenance.evidence.exitCode ?? "unknown"}`,
172251
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CliResultEvidence, { evidence: provenance.evidence })
172252
+ });
172253
+ }
171754
172254
  function StaticArtifactOutputs({ artifacts }) {
171755
172255
  if (artifacts.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
171756
172256
  className: "text-muted-foreground",
@@ -171954,6 +172454,220 @@ function EvidenceList({ label, values }) {
171954
172454
  });
171955
172455
  }
171956
172456
  //#endregion
172457
+ //#region src/components/evidence-workspace.tsx
172458
+ /**
172459
+ * Orthogonal intents (created 2026-08-28 Asia/Shanghai):
172460
+ * 1. Own the Change Evidence tab's container-responsive list-detail workspace topology.
172461
+ * 2. Preserve the decision-plane evidence layer order (summary/paths -> requirement diffs ->
172462
+ * archived validation -> CLI/raw payload) in keyboard-reachable list rows.
172463
+ * 3. Derive row chips only from settled section facts; never fabricate counts or verdicts.
172464
+ * 4. Keep the crowded drill presentational: the detail replaces the list with a back
172465
+ * affordance, and back restores the list without unmounting settled evidence; focus
172466
+ * follows the drill (row -> back affordance -> originating row) so keyboard users never
172467
+ * land on a hidden element.
172468
+ * 5. Keep sub-selection local runtime state — it never enters routes or browser storage.
172469
+ *
172470
+ * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
172471
+ */
172472
+ /**
172473
+ * Spacious threshold: below this inline size the workspace collapses to one column and the
172474
+ * list becomes the drill entry surface. 640px sustains the widest list rail (280px) plus a
172475
+ * ~360px detail reading column — the minimum at which the `@[32rem]` fact/provenance grids
172476
+ * inside every section still render as two columns without horizontal pressure.
172477
+ */
172478
+ var EVIDENCE_SPACIOUS_MIN_WIDTH = 640;
172479
+ var CHIP_TONE_CLASS = {
172480
+ neutral: "border-border bg-muted text-muted-foreground",
172481
+ positive: "border border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
172482
+ negative: "border border-destructive/40 bg-destructive/10 text-destructive",
172483
+ unavailable: "border-border bg-muted/60 text-muted-foreground",
172484
+ error: "border border-destructive/40 bg-destructive/10 text-destructive"
172485
+ };
172486
+ /**
172487
+ * Container-width topology state through the same ResizeObserver seam the Git list-detail
172488
+ * layout uses: the observed box is the workspace container itself, never the viewport, so
172489
+ * the drill semantics track the CSS `@container` grid breakpoint (640px) exactly.
172490
+ */
172491
+ function useSpaciousEvidenceLayout() {
172492
+ const ref = (0, import_react.useRef)(null);
172493
+ const [spacious, setSpacious] = (0, import_react.useState)(false);
172494
+ (0, import_react.useEffect)(() => {
172495
+ const node = ref.current;
172496
+ if (!node || typeof ResizeObserver === "undefined") return;
172497
+ const observer = new ResizeObserver(([entry]) => {
172498
+ setSpacious((entry?.contentRect.width ?? 0) >= EVIDENCE_SPACIOUS_MIN_WIDTH);
172499
+ });
172500
+ observer.observe(node);
172501
+ return () => {
172502
+ observer.disconnect();
172503
+ };
172504
+ }, []);
172505
+ return {
172506
+ ref,
172507
+ spacious
172508
+ };
172509
+ }
172510
+ /** Container-responsive list-detail workspace that carries the whole Change Evidence tab. */
172511
+ function EvidenceWorkspace({ changeId, status, referenceEvidence }) {
172512
+ const { ref, spacious } = useSpaciousEvidenceLayout();
172513
+ const [selectedId, setSelectedId] = (0, import_react.useState)("summary-paths");
172514
+ const [drilled, setDrilled] = (0, import_react.useState)(false);
172515
+ const rowRefs = (0, import_react.useRef)(/* @__PURE__ */ new Map());
172516
+ const backRef = (0, import_react.useRef)(null);
172517
+ const drilledByRowId = (0, import_react.useRef)(null);
172518
+ const pendingRestoreRowId = (0, import_react.useRef)(null);
172519
+ const backHadFocus = (0, import_react.useRef)(false);
172520
+ const [diffChip, setDiffChip] = (0, import_react.useState)(null);
172521
+ const [validationChip, setValidationChip] = (0, import_react.useState)(null);
172522
+ const handleDiffChip = (0, import_react.useCallback)((chip) => {
172523
+ setDiffChip(chip);
172524
+ }, []);
172525
+ const handleValidationChip = (0, import_react.useCallback)((chip) => {
172526
+ setValidationChip(chip);
172527
+ }, []);
172528
+ const sections = (0, import_react.useMemo)(() => {
172529
+ const liveSections = status.provenance.kind === "static" ? [] : [{
172530
+ id: "cli-result",
172531
+ label: "CLI result",
172532
+ content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeCliResultSection, { status })
172533
+ }];
172534
+ return [
172535
+ {
172536
+ id: "summary-paths",
172537
+ label: "Summary & paths",
172538
+ content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeSummaryPathsSection, {
172539
+ status,
172540
+ referenceEvidence
172541
+ })
172542
+ },
172543
+ {
172544
+ id: "requirement-diffs",
172545
+ label: "Requirement diffs",
172546
+ chip: diffChip,
172547
+ content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeDiffEvidence, {
172548
+ changeId,
172549
+ onChip: handleDiffChip
172550
+ })
172551
+ },
172552
+ {
172553
+ id: "archived-validation",
172554
+ label: "Archived validation",
172555
+ chip: validationChip,
172556
+ content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationEvidence, { onChip: handleValidationChip })
172557
+ },
172558
+ ...liveSections
172559
+ ];
172560
+ }, [
172561
+ changeId,
172562
+ diffChip,
172563
+ handleDiffChip,
172564
+ handleValidationChip,
172565
+ referenceEvidence,
172566
+ status,
172567
+ validationChip
172568
+ ]);
172569
+ const activeSection = sections.find((section) => section.id === selectedId) ?? sections[0];
172570
+ const showList = spacious || !drilled;
172571
+ const showDetail = spacious || drilled;
172572
+ const selectSection = (0, import_react.useCallback)((id) => {
172573
+ setSelectedId(id);
172574
+ if (!spacious) {
172575
+ drilledByRowId.current = id;
172576
+ setDrilled(true);
172577
+ }
172578
+ }, [spacious]);
172579
+ const backToList = (0, import_react.useCallback)(() => {
172580
+ pendingRestoreRowId.current = drilledByRowId.current;
172581
+ drilledByRowId.current = null;
172582
+ setDrilled(false);
172583
+ }, []);
172584
+ (0, import_react.useEffect)(() => {
172585
+ if (drilled && !spacious) backRef.current?.focus();
172586
+ else if (!drilled) {
172587
+ const rowId = pendingRestoreRowId.current;
172588
+ pendingRestoreRowId.current = null;
172589
+ if (rowId) rowRefs.current.get(rowId)?.focus();
172590
+ } else if (drilled && spacious && backHadFocus.current) {
172591
+ backHadFocus.current = false;
172592
+ rowRefs.current.get(selectedId)?.focus();
172593
+ }
172594
+ }, [
172595
+ drilled,
172596
+ spacious,
172597
+ selectedId
172598
+ ]);
172599
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", {
172600
+ ref,
172601
+ "aria-label": "Change Evidence",
172602
+ "data-evidence-workspace": "",
172603
+ "data-evidence-topology": spacious ? "spacious" : "crowded",
172604
+ className: "@container/evidence-workspace flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
172605
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172606
+ className: "@[40rem]:grid-cols-[clamp(12.5rem,24cqw,17.5rem)_minmax(0,1fr)] grid min-h-0 min-w-0 flex-1 grid-cols-1 overflow-hidden",
172607
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", {
172608
+ "aria-label": "Evidence sections",
172609
+ "data-evidence-pane": "list",
172610
+ hidden: !showList || void 0,
172611
+ className: cn$1("scrollbar-thin scrollbar-track-transparent border-border/60 @[40rem]:border-r min-h-0 min-w-0 overflow-y-auto overflow-x-hidden overscroll-contain", !showList && "hidden"),
172612
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
172613
+ className: "divide-border/20 m-0 list-none divide-y p-0",
172614
+ children: sections.map((section) => {
172615
+ const selected = section.id === activeSection.id;
172616
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
172617
+ ref: (node) => {
172618
+ if (node) rowRefs.current.set(section.id, node);
172619
+ else rowRefs.current.delete(section.id);
172620
+ },
172621
+ type: "button",
172622
+ "data-evidence-row": section.id,
172623
+ "aria-current": selected ? "true" : void 0,
172624
+ onClick: () => selectSection(section.id),
172625
+ className: cn$1("focus-visible:ring-primary hover:bg-muted flex min-h-10 w-full min-w-0 items-center justify-between gap-2 px-3 text-left text-xs outline-none focus-visible:ring-2 focus-visible:ring-inset", selected && "bg-primary text-primary-foreground hover:bg-primary font-medium"),
172626
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
172627
+ className: "min-w-0 truncate",
172628
+ children: section.label
172629
+ }), section.chip ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
172630
+ tone: "custom",
172631
+ size: "xs",
172632
+ className: CHIP_TONE_CLASS[section.chip.tone],
172633
+ children: section.chip.label
172634
+ }) : null]
172635
+ }) }, section.id);
172636
+ })
172637
+ })
172638
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172639
+ "data-evidence-pane": "detail",
172640
+ "data-change-evidence-scroll-owner": "",
172641
+ 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"),
172643
+ children: [!spacious && drilled ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
172644
+ ref: backRef,
172645
+ type: "button",
172646
+ "data-evidence-back": "",
172647
+ "aria-label": "Back to evidence list",
172648
+ onFocus: () => {
172649
+ backHadFocus.current = true;
172650
+ },
172651
+ onBlur: () => {
172652
+ backHadFocus.current = false;
172653
+ },
172654
+ onClick: backToList,
172655
+ className: "bg-background/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
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowLeft, {
172657
+ className: "h-3.5 w-3.5 shrink-0",
172658
+ "aria-hidden": true
172659
+ }), "Evidence list"]
172660
+ }) : null, sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
172661
+ "data-evidence-detail": section.id,
172662
+ hidden: section.id !== activeSection.id,
172663
+ className: "min-w-0 px-4 pb-4",
172664
+ children: section.content
172665
+ }, section.id))]
172666
+ })]
172667
+ })
172668
+ });
172669
+ }
172670
+ //#endregion
171957
172671
  //#region src/components/opsx/change-command-bar.tsx
171958
172672
  /**
171959
172673
  * Orthogonal intents (updated 2026-08-03 Asia/Shanghai):
@@ -172189,12 +172903,13 @@ function RootActionNotice({ state }) {
172189
172903
  //#endregion
172190
172904
  //#region src/routes/change-view.tsx
172191
172905
  /**
172192
- * Orthogonal intents (updated 2026-08-03 Asia/Shanghai):
172906
+ * Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
172193
172907
  * 1. Render schema-aware change artifacts and source files while retaining terminal status errors.
172194
172908
  * 2. Dispatch change workflows through routed compose/verify surfaces and the shared Operator launcher.
172195
172909
  * 3. Lock every change workflow action behind current Root Context and Status projection authority.
172196
172910
  * 4. Present Apply progress directly and expose project context/guidance through a Header Action Dialog.
172197
172911
  * 5. Keep compact Change facts in subtitle badges while routing complete CLI evidence through a dedicated tab.
172912
+ * 6. Mount the container-responsive list-detail Evidence workspace as the sole Evidence tab surface.
172198
172913
  *
172199
172914
  * Original request (2026-07-15): "Root-dependent actions remain locked until root selection succeeds."
172200
172915
  * Review request (2026-07-23): "代码已经提交,开始review。如果有问题,那么可更新change。"
@@ -172203,6 +172918,9 @@ function RootActionNotice({ state }) {
172203
172918
  * Original request (2026-08-03): move complete Change evidence into a dedicated tab page.
172204
172919
  * Owner correction (2026-08-03): move Actions inline with the title, unify subtitle badges, and localize unavailable Tooltips.
172205
172920
  * Original request (2026-08-15): 刷新/解析中状态收敛为副标题行内的 shiny 徽章,不再占据 statusRegion 块。
172921
+ * Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。" — the Evidence
172922
+ * tab gains the 1.11-gated CLI MODIFIED-delta diff evidence beside the existing layers.
172923
+ * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
172206
172924
  */
172207
172925
  function ChangeView() {
172208
172926
  const { changeId } = useParams({ from: "/changes/$changeId" });
@@ -172276,12 +172994,10 @@ function ChangeView() {
172276
172994
  id: "evidence",
172277
172995
  label: "Evidence",
172278
172996
  icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileSearch, { className: "h-4 w-4" }),
172279
- content: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
172280
- className: "flex min-h-0 min-w-0 flex-1 flex-col",
172281
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeEvidencePanel, {
172282
- status,
172283
- referenceEvidence
172284
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArchivedValidationEvidence, {})]
172997
+ content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EvidenceWorkspace, {
172998
+ changeId,
172999
+ status,
173000
+ referenceEvidence
172285
173001
  })
172286
173002
  }] : [], [referenceEvidence, status]);
172287
173003
  const hasReferenceFailures = referenceEvidence.state !== "unavailable" && referenceEvidence.references.some((reference) => reference.status.some((diagnostic) => diagnostic.severity === "error"));
@@ -172400,7 +173116,7 @@ var CONFIG_GUIDE_STAGE_META = {
172400
173116
  //#region src/components/config/config-guide.tsx
172401
173117
  var ConfigGuideContext = (0, import_react.createContext)(null);
172402
173118
  (0, import_react.lazy)(async () => {
172403
- return { default: (await import("./config-guide-presentation-CcpWbzbF.js")).ConfigGuidePresentationLayer };
173119
+ return { default: (await import("./config-guide-presentation-BfkVCRQq.js")).ConfigGuidePresentationLayer };
172404
173120
  });
172405
173121
  /** Access the root-owned adaptive Guide runtime. */
172406
173122
  function useConfigGuide() {