@openspecui/web 12.0.0 → 13.0.1

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 (69) hide show
  1. package/dist/assets/{App-Dmag08k5.js → App-C6nQouC6.js} +153 -153
  2. package/dist/assets/{App-BagQkLCd.css → App-CYwWbLgm.css} +1 -1
  3. package/dist/assets/{main-DXjJbv3-.js → main-CGJ5sQ3N.js} +2 -2
  4. package/dist/assets/{trpc-CENMN-Kx.js → trpc-Cq_wSpa5.js} +1 -1
  5. package/dist/index.html +1 -1
  6. package/dist-ssg/client/.vite/ssr-manifest.json +59 -29
  7. package/dist-ssg/client/assets/CanvasRenderer-Dxe-hfnN.js +1 -0
  8. package/dist-ssg/client/assets/WebGLRenderer-CUJXjtiP.js +1 -0
  9. package/dist-ssg/client/assets/WebGPURenderer-CZL-JNBq.js +1 -0
  10. package/dist-ssg/client/assets/browserAll-5wBADmKd.js +1 -0
  11. package/dist-ssg/client/assets/{config-guide-presentation-GtsojPuN.js → config-guide-presentation-DqNeQzUr.js} +1 -1
  12. package/dist-ssg/client/assets/dist-9A8186dQ.js +1 -0
  13. package/dist-ssg/client/assets/{dist-BxTQbErr.js → dist-BD3jMQZ6.js} +1 -1
  14. package/dist-ssg/client/assets/dist-BMEQqWwb.js +1 -0
  15. package/dist-ssg/client/assets/dist-BTKdGHSA.js +1 -0
  16. package/dist-ssg/client/assets/{dist-C7lTRiju.js → dist-Bbhzl31A.js} +1 -1
  17. package/dist-ssg/client/assets/{dist-BAP9yhhm.js → dist-CY1qnMaG.js} +1 -1
  18. package/dist-ssg/client/assets/{dist-CI3zBObR.js → dist-CaeREplI.js} +1 -1
  19. package/dist-ssg/client/assets/{dist-Df3fSUJ8.js → dist-CdubN8-m.js} +1 -1
  20. package/dist-ssg/client/assets/{dist-B0xIEOgo.js → dist-DImGv92l.js} +1 -1
  21. package/dist-ssg/client/assets/{dist-DHkPjBBo.js → dist-DvFFLa-_.js} +1 -1
  22. package/dist-ssg/client/assets/{dist-CJOMMo-D.js → dist-DvI6Bh6U.js} +1 -1
  23. package/dist-ssg/client/assets/{dist-Cgf7W726.js → dist-FrX9lO7v.js} +1 -1
  24. package/dist-ssg/client/assets/{ghostty-web-VZE4TZBO.js → ghostty-web-iJUDy0Q_.js} +1 -1
  25. package/dist-ssg/client/assets/{index-CS0xsSqt.css → index-CMfi0IZJ.css} +1 -1
  26. package/dist-ssg/client/assets/{index.ssg-m0qZ-Tbv.js → index.ssg-C1gQDtR3.js} +134 -134
  27. package/dist-ssg/client/assets/{init-0qJSx79q.js → init-CXOzxy8a.js} +1 -1
  28. package/dist-ssg/client/assets/{trpc-D4bSp4J9.js → trpc-DeGTgf0N.js} +1 -1
  29. package/dist-ssg/client/assets/webworkerAll-D2PWaP7M.js +1 -0
  30. package/dist-ssg/client/index.ssg.html +2 -2
  31. package/dist-ssg/server/assets/CanvasRenderer-B1MUQY2W.js +3 -0
  32. package/dist-ssg/server/assets/WebGLRenderer-DIOoeqKv.js +3 -0
  33. package/dist-ssg/server/assets/WebGPURenderer-hzdCHpRg.js +3 -0
  34. package/dist-ssg/server/assets/{browserAll-Da2y8ybl.js → browserAll-C3aU2kkg.js} +2 -2
  35. package/dist-ssg/server/assets/{config-guide-presentation-GWnVFKTW.js → config-guide-presentation-BQdHuc5R.js} +1 -1
  36. package/dist-ssg/server/assets/{dist-DHhdkqG1.js → dist-BrgApT3v.js} +1 -1
  37. package/dist-ssg/server/assets/{dist-QLG95fVW.js → dist-BuA1hNQD.js} +1 -1
  38. package/dist-ssg/server/assets/{dist-CmE7gK9r.js → dist-C8tud7al.js} +1 -1
  39. package/dist-ssg/server/assets/{dist-dHhPmrtl.js → dist-CYFz-Xe6.js} +1 -1
  40. package/dist-ssg/server/assets/{dist-C8mczL_o.js → dist-CeAwBeY0.js} +1 -1
  41. package/dist-ssg/server/assets/dist-DQfK_0MA.js +3 -0
  42. package/dist-ssg/server/assets/{dist-Bk9be2-W.js → dist-DVq3OitZ.js} +1 -1
  43. package/dist-ssg/server/assets/dist-DhIAeIAf.js +3 -0
  44. package/dist-ssg/server/assets/{dist-CRw-jyve.js → dist-DoPtyXvU.js} +1 -1
  45. package/dist-ssg/server/assets/{dist-A6g9ScYS.js → dist-cd39lbM_.js} +1 -1
  46. package/dist-ssg/server/assets/{dist-D3Ubfaie.js → dist-uLS_wgVI.js} +1 -1
  47. package/dist-ssg/server/assets/dist-wVpQUanK.js +3 -0
  48. package/dist-ssg/server/assets/{entry-server-B1byBTHL.js → entry-server-DOzQvxeU.js} +459 -90
  49. package/dist-ssg/server/assets/{init-BCpyot27.js → init-Dw3wIW5D.js} +1 -1
  50. package/dist-ssg/server/assets/trpc-CE2cP14O.js +3 -0
  51. package/dist-ssg/server/assets/webworkerAll-CMJ1pR5p.js +4 -0
  52. package/dist-ssg/server/ssr-entry-manifest.json +24 -24
  53. package/package.json +3 -3
  54. package/dist-ssg/client/assets/CanvasRenderer-B3YNEZKU.js +0 -1
  55. package/dist-ssg/client/assets/WebGLRenderer-91FdO4XE.js +0 -1
  56. package/dist-ssg/client/assets/WebGPURenderer-BcSREi3g.js +0 -1
  57. package/dist-ssg/client/assets/browserAll-CRvGxmXW.js +0 -1
  58. package/dist-ssg/client/assets/dist-Bsojfco7.js +0 -1
  59. package/dist-ssg/client/assets/dist-fJz8f69P.js +0 -1
  60. package/dist-ssg/client/assets/dist-we8a11kz.js +0 -1
  61. package/dist-ssg/client/assets/webworkerAll-BUpVAcIt.js +0 -1
  62. package/dist-ssg/server/assets/CanvasRenderer-eDcOd6Sl.js +0 -3
  63. package/dist-ssg/server/assets/WebGLRenderer-BYGgdFoJ.js +0 -3
  64. package/dist-ssg/server/assets/WebGPURenderer-CS5mt9ch.js +0 -3
  65. package/dist-ssg/server/assets/dist-C8ZGbZgL.js +0 -3
  66. package/dist-ssg/server/assets/dist-D2ilXjzO.js +0 -3
  67. package/dist-ssg/server/assets/dist-DbHDr3r9.js +0 -3
  68. package/dist-ssg/server/assets/trpc-D5UIUAYV.js +0 -3
  69. package/dist-ssg/server/assets/webworkerAll-Dg825OUg.js +0 -4
@@ -29769,11 +29769,14 @@ objectType({
29769
29769
  * 1. Publish browser-safe lenient Spec/active-Change entry schemas for Store-content projection.
29770
29770
  * 2. Define the additive Store-content compatibility fact and demand-driven content kind.
29771
29771
  * 3. Keep this entry free of Node runtime dependencies for hosted browser consumers.
29772
+ * 4. Model the OpenSpec 1.13.1 `nested` member on Store active-Change entries so the
29773
+ * server-side content projection can exclude namespace folders from its projected list.
29772
29774
  *
29773
29775
  * Original request (2026-07-30): "Stores 完全可以融入 `Environment Center` 这个东西,就跟 Config 和 Context 的关系一样。"
29774
29776
  * Derived boundary (2026-07-30): Store UI identity is `(backend-issued envUri, Store id)`; Store Detail
29775
29777
  * shows readonly content summaries sourced from typed `list --specs|--changes --store <id>`.
29776
29778
  * Spec: hosted-environment-delivery › "Environment-Scoped Store Content Projection".
29779
+ * Original request (2026-09-17): "Openspec 1.13.1 释放了…" — change-list nested/warnings projection (update-openspec-cli-1131 Slice 2).
29777
29780
  *
29778
29781
  * Capability visibility is a compatibility fact, not authorization. A backend that omits
29779
29782
  * `stores.content.inspect` simply does not advertise the content projection; the App renders the
@@ -29794,7 +29797,8 @@ var StoreContentChangeEntrySchema = objectType({
29794
29797
  "no-tasks",
29795
29798
  "complete",
29796
29799
  "in-progress"
29797
- ])
29800
+ ]),
29801
+ nested: arrayType(stringType()).optional()
29798
29802
  }).passthrough();
29799
29803
  objectType({
29800
29804
  specs: arrayType(StoreContentSpecEntrySchema).default([]),
@@ -30908,7 +30912,7 @@ var NavController = class {
30908
30912
  this.storageKey = scopedStorageKey;
30909
30913
  this.rebindProjectScopedLayout(scopedStorageKey);
30910
30914
  }
30911
- const { trpcClient } = await import("./trpc-D5UIUAYV.js");
30915
+ const { trpcClient } = await import("./trpc-CE2cP14O.js");
30912
30916
  const remote = parsePersistedLayout(await trpcClient.kv.get.query({ key: this.storageKey }));
30913
30917
  if (remote) {
30914
30918
  if (remote.updatedAt > this.state.updatedAt) this.dispatch({
@@ -31051,7 +31055,7 @@ var NavController = class {
31051
31055
  this.cancelPersistTimer();
31052
31056
  this.persistTimer = setTimeout(() => {
31053
31057
  this.persistTimer = null;
31054
- import("./trpc-D5UIUAYV.js").then(({ trpcClient }) => trpcClient.kv.set.mutate({
31058
+ import("./trpc-CE2cP14O.js").then(({ trpcClient }) => trpcClient.kv.set.mutate({
31055
31059
  key: this.storageKey,
31056
31060
  value: {
31057
31061
  mainTabs: this.state.mainTabs,
@@ -38940,6 +38944,54 @@ var R$2 = class R$2 {
38940
38944
  function F$1(t) {
38941
38945
  throw new I$2(t);
38942
38946
  }
38947
+ //#endregion
38948
+ //#region ../core/src/cli-contracts/workflow.ts
38949
+ /**
38950
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
38951
+ * 1. Model camelCase workflow JSON independently from Store-family JSON.
38952
+ * 2. Preserve strict, archived, and bulk Validate plus Archive outcomes, including failure payloads.
38953
+ * 3. Preserve multiline requirement bodies from `show --json`.
38954
+ * 4. Preserve complete admitted-line (1.10/1.11) Status and operation-Instruction contracts as CLI facts.
38955
+ * 5. Export the successful Spec-document schema for browser-safe projection validation.
38956
+ * 6. Export the root-less Status payload fields and Requirement shape shared with the
38957
+ * OpenSpec 1.11 batch Status and show --diff contracts.
38958
+ * 7. Model the OpenSpec 1.12 `validate --report findings` document beside (never inside) the
38959
+ * full Validate report, sharing the bulk-item and summary shapes while keeping decoding
38960
+ * independent of the process exit code and of full-report validation truth. Decode owns
38961
+ * the upstream-guaranteed invariants (non-empty per-item issues, returnedItems bounded
38962
+ * by totalItems), and the union guard validates the discriminator shape rather than
38963
+ * mere `report`-key presence.
38964
+ * 8. Type the OpenSpec 1.13 Apply Instructions `missingPrerequisites` (build-order closure,
38965
+ * present even when ready) and `warnings` (no-delta-specs advisory) as additive optional
38966
+ * success members that never gain default empty arrays, never alter `state`/`progress`/
38967
+ * `tasks`/`missingArtifacts` semantics, and stay verbatim CLI evidence.
38968
+ * 9. Type the OpenSpec 1.13.1 change-list `nested` entry member and top-level `warnings`
38969
+ * array as additive optional facts (absent when empty, never null): an entry carrying
38970
+ * `nested` is a namespace folder, not an actionable change; `code` stays an open string
38971
+ * because an in-window patch may add codes beyond `nested_change_directory`.
38972
+ *
38973
+ * Original request (2026-07-15): "为不同命令建立强类型适配器,不实现平行解析规则。"
38974
+ * Original request (2026-07-26): "展开全面的接口升级和内核升级和测试升级。"
38975
+ * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
38976
+ * Original request (2026-08-28): "直接将 0.10.0 和 0.11.0 一起适配,然后发布 v11。"
38977
+ * Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
38978
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
38979
+ * Original request (2026-09-17): "Openspec 1.13.1 释放了…" — change-list nested/warnings projection (update-openspec-cli-1131 Slice 2).
38980
+ */
38981
+ /**
38982
+ * One top-level change-list hygiene warning (OpenSpec 1.13.1 `list --json`).
38983
+ *
38984
+ * `code` is an open string, not a literal: the upstream contract documents
38985
+ * `nested_change_directory` as the only current code while reserving room for more, so an
38986
+ * in-window patch adding a code must survive decode as evidence instead of failing the
38987
+ * whole document. The whole array is absent when empty (never `null`, never `[]`).
38988
+ */
38989
+ var CliChangeListWarningSchema = objectType({
38990
+ code: stringType(),
38991
+ name: stringType(),
38992
+ nested: arrayType(stringType()),
38993
+ message: stringType()
38994
+ }).passthrough();
38943
38995
  objectType({
38944
38996
  changes: arrayType(objectType({
38945
38997
  name: stringType(),
@@ -38950,8 +39002,10 @@ objectType({
38950
39002
  "no-tasks",
38951
39003
  "complete",
38952
39004
  "in-progress"
38953
- ])
39005
+ ]),
39006
+ nested: arrayType(stringType()).optional()
38954
39007
  }).passthrough()),
39008
+ warnings: arrayType(CliChangeListWarningSchema).optional(),
38955
39009
  root: CliRootSchema.nullable(),
38956
39010
  status: arrayType(CliDiagnosticSchema).optional()
38957
39011
  }).passthrough();
@@ -39116,6 +39170,8 @@ unionType([objectType({
39116
39170
  "ready"
39117
39171
  ]),
39118
39172
  missingArtifacts: arrayType(stringType()).optional(),
39173
+ missingPrerequisites: arrayType(stringType()).optional(),
39174
+ warnings: arrayType(stringType()).optional(),
39119
39175
  instruction: stringType(),
39120
39176
  references: arrayType(CliReferenceIndexEntrySchema).optional(),
39121
39177
  context: stringType().optional(),
@@ -43343,15 +43399,19 @@ function createApplyInstructionProgress(input, trackedTaskProgress) {
43343
43399
  //#endregion
43344
43400
  //#region ../core/src/opsx-types.ts
43345
43401
  /**
43346
- * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
43402
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
43347
43403
  * 1. Publish runtime schemas for final Projection Work payloads, including transformed Apply progress.
43348
43404
  * 2. Keep isPlanningComplete as the authoritative planning fact over any local tracked alias.
43349
43405
  * 3. Carry CLI status evidence, diagnostics, and per-artifact requires as typed facts.
43350
43406
  * 4. Preserve root-context and store projections as browser-safe contracts.
43351
43407
  * 5. Keep projection notices distinct from payload data so failures never masquerade as results.
43408
+ * 6. Project the OpenSpec 1.13 Apply `warnings` and `missingPrerequisites` fields through the
43409
+ * input and final projection schemas verbatim: optional everywhere, never defaulted to
43410
+ * empty arrays, and never allowed to alter state/progress/tasks semantics.
43352
43411
  *
43353
43412
  * Original request (2026-07-15): "为内核载荷建立强类型。"
43354
43413
  * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
43414
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
43355
43415
  */
43356
43416
  /** Runtime schema for one JSON value retained from a CLI Status stdout document. */
43357
43417
  var OpsxCliJsonValueSchema = lazyType(() => unionType([
@@ -43445,6 +43505,8 @@ var ApplyInstructionsInputSchema = objectType({
43445
43505
  "ready"
43446
43506
  ]),
43447
43507
  missingArtifacts: arrayType(stringType()).optional(),
43508
+ missingPrerequisites: arrayType(stringType()).optional(),
43509
+ warnings: arrayType(stringType()).optional(),
43448
43510
  instruction: stringType(),
43449
43511
  references: arrayType(CliReferenceIndexEntrySchema).optional(),
43450
43512
  context: stringType().optional(),
@@ -43494,6 +43556,8 @@ var ApplyInstructionsProjectionSchema = objectType({
43494
43556
  "ready"
43495
43557
  ]),
43496
43558
  missingArtifacts: arrayType(stringType()).optional(),
43559
+ missingPrerequisites: arrayType(stringType()).optional(),
43560
+ warnings: arrayType(stringType()).optional(),
43497
43561
  instruction: stringType(),
43498
43562
  references: arrayType(CliReferenceIndexEntrySchema).optional(),
43499
43563
  context: stringType().optional(),
@@ -43584,8 +43648,13 @@ var TemplateContentMapSchema = recordType(stringType(), TemplateContentSchema);
43584
43648
  * 2. Define the runtime-environment Environment Global projection contract.
43585
43649
  * 3. Publish browser-safe lifecycle Pull schemas without importing Node-owned Core modules.
43586
43650
  * 4. Keep projection data discriminated across Status and Artifact/Apply/Archive Instructions.
43651
+ * 5. Model the OpenSpec 1.13.1 change-list namespace facts beside the actionable set:
43652
+ * `entries`/`value` stay actionable-only, `namespaces` is the single structural
43653
+ * namespace-name set for row builders, and `warnings` is passthrough display evidence
43654
+ * (absent when the CLI omitted it, never a synthesized empty array).
43587
43655
  *
43588
43656
  * Original request (2026-07-26): "展开全面的接口升级和内核升级和测试升级。"
43657
+ * Original request (2026-09-17): "Openspec 1.13.1 释放了…" — change-list nested/warnings projection (update-openspec-cli-1131 Slice 2).
43589
43658
  */
43590
43659
  /** Runtime selector for one Planning-root CLI-backed projection. */
43591
43660
  var PlanningCliProjectionSelectorSchema = discriminatedUnionType("kind", [
@@ -43647,6 +43716,8 @@ var PlanningCliProjectionStateSchema = createCliProjectionStateSchema(discrimina
43647
43716
  "in-progress"
43648
43717
  ])
43649
43718
  })),
43719
+ namespaces: arrayType(stringType()),
43720
+ warnings: arrayType(CliChangeListWarningSchema).optional(),
43650
43721
  evidence: CliProjectionCommandEvidenceSchema
43651
43722
  }),
43652
43723
  objectType({
@@ -44853,6 +44924,25 @@ function useOpsxApplyInstructionsSubscription(input) {
44853
44924
  isLoading: false
44854
44925
  };
44855
44926
  }
44927
+ /**
44928
+ * OpenSpec 1.13.1 change-list hygiene warnings (e.g. `nested_change_directory`).
44929
+ *
44930
+ * Display evidence only: the CLI's verbatim warning array rides beside the actionable
44931
+ * change list; it never gates row visibility or mutation authority. Static publication
44932
+ * carries no CLI lifecycle evidence, so the static loader resolves no warnings — an empty
44933
+ * list there is absence of evidence, not a fabricated clean bill of health.
44934
+ */
44935
+ function useOpsxChangeListHygieneWarningsSubscription() {
44936
+ return useCliProjectionSubscription({
44937
+ selector: { kind: "opsx-change-list" },
44938
+ selectData(data) {
44939
+ if (data.kind !== "opsx-change-list") throw new Error(`Expected opsx-change-list projection, received ${data.kind}.`);
44940
+ return data.warnings ?? [];
44941
+ },
44942
+ staticLoader: async () => [],
44943
+ cacheKey: "opsx.changeListHygieneWarnings"
44944
+ });
44945
+ }
44856
44946
  function useOpsxArtifactOutputSubscription(changeId, outputPath) {
44857
44947
  return useSubscription((0, import_react.useCallback)((callbacks) => {
44858
44948
  if (!changeId || !outputPath) {
@@ -46966,6 +47056,32 @@ var ListChecks = createLucideIcon("ListChecks", [
46966
47056
  key: "oe0vm4"
46967
47057
  }]
46968
47058
  ]);
47059
+ var ListOrdered = createLucideIcon("ListOrdered", [
47060
+ ["path", {
47061
+ d: "M10 12h11",
47062
+ key: "6m4ad9"
47063
+ }],
47064
+ ["path", {
47065
+ d: "M10 18h11",
47066
+ key: "11hvi2"
47067
+ }],
47068
+ ["path", {
47069
+ d: "M10 6h11",
47070
+ key: "c7qv1k"
47071
+ }],
47072
+ ["path", {
47073
+ d: "M4 10h2",
47074
+ key: "16xx2s"
47075
+ }],
47076
+ ["path", {
47077
+ d: "M4 6h1v4",
47078
+ key: "cnovpq"
47079
+ }],
47080
+ ["path", {
47081
+ d: "M6 18H4c0-1 2-2 2-3s-1-1.5-2-1",
47082
+ key: "m9a95d"
47083
+ }]
47084
+ ]);
46969
47085
  var ListTodo = createLucideIcon("ListTodo", [
46970
47086
  ["rect", {
46971
47087
  x: "3",
@@ -71280,7 +71396,7 @@ var browserExt = {
71280
71396
  },
71281
71397
  test: () => true,
71282
71398
  load: async () => {
71283
- await import("./browserAll-Da2y8ybl.js");
71399
+ await import("./browserAll-C3aU2kkg.js");
71284
71400
  }
71285
71401
  };
71286
71402
  //#endregion
@@ -71293,7 +71409,7 @@ var webworkerExt = {
71293
71409
  },
71294
71410
  test: () => typeof self !== "undefined" && self.WorkerGlobalScope !== void 0,
71295
71411
  load: async () => {
71296
- await import("./webworkerAll-Dg825OUg.js");
71412
+ await import("./webworkerAll-CMJ1pR5p.js");
71297
71413
  }
71298
71414
  };
71299
71415
  //#endregion
@@ -73887,7 +74003,7 @@ async function autoDetectRenderer(options) {
73887
74003
  for (let i = 0; i < preferredOrder.length; i++) {
73888
74004
  const rendererType = preferredOrder[i];
73889
74005
  if (rendererType === "webgpu" && await isWebGPUSupported()) {
73890
- const { WebGPURenderer } = await import("./WebGPURenderer-CS5mt9ch.js");
74006
+ const { WebGPURenderer } = await import("./WebGPURenderer-hzdCHpRg.js");
73891
74007
  RendererClass = WebGPURenderer;
73892
74008
  finalOptions = {
73893
74009
  ...options,
@@ -73895,7 +74011,7 @@ async function autoDetectRenderer(options) {
73895
74011
  };
73896
74012
  break;
73897
74013
  } else if (rendererType === "webgl" && isWebGLSupported(options.failIfMajorPerformanceCaveat ?? AbstractRenderer.defaultOptions.failIfMajorPerformanceCaveat)) {
73898
- const { WebGLRenderer } = await import("./WebGLRenderer-BYGgdFoJ.js");
74014
+ const { WebGLRenderer } = await import("./WebGLRenderer-DIOoeqKv.js");
73899
74015
  RendererClass = WebGLRenderer;
73900
74016
  finalOptions = {
73901
74017
  ...options,
@@ -73903,7 +74019,7 @@ async function autoDetectRenderer(options) {
73903
74019
  };
73904
74020
  break;
73905
74021
  } else if (rendererType === "canvas") {
73906
- const { CanvasRenderer } = await import("./CanvasRenderer-eDcOd6Sl.js");
74022
+ const { CanvasRenderer } = await import("./CanvasRenderer-B1MUQY2W.js");
73907
74023
  RendererClass = CanvasRenderer;
73908
74024
  finalOptions = {
73909
74025
  ...options,
@@ -97652,7 +97768,7 @@ var TerminalController = class {
97652
97768
  if (this.configPersistTimer) clearTimeout(this.configPersistTimer);
97653
97769
  this.configPersistTimer = setTimeout(() => {
97654
97770
  this.configPersistTimer = null;
97655
- import("./trpc-D5UIUAYV.js").then(({ trpcClient }) => {
97771
+ import("./trpc-CE2cP14O.js").then(({ trpcClient }) => {
97656
97772
  trpcClient.config.update.mutate({ terminal: { fontSize: this.config.fontSize } });
97657
97773
  }).catch(() => {});
97658
97774
  }, CONFIG_PERSIST_DEBOUNCE);
@@ -108213,7 +108329,7 @@ var languages = [
108213
108329
  name: "CSS",
108214
108330
  extensions: ["css"],
108215
108331
  load() {
108216
- return import("./dist-C8ZGbZgL.js").then((m) => m.css());
108332
+ return import("./dist-wVpQUanK.js").then((m) => m.css());
108217
108333
  }
108218
108334
  }),
108219
108335
  /* @__PURE__ */ LanguageDescription.of({
@@ -108233,7 +108349,7 @@ var languages = [
108233
108349
  "hbs"
108234
108350
  ],
108235
108351
  load() {
108236
- return import("./dist-dHhPmrtl.js").then((m) => m.html());
108352
+ return import("./dist-CYFz-Xe6.js").then((m) => m.html());
108237
108353
  }
108238
108354
  }),
108239
108355
  /* @__PURE__ */ LanguageDescription.of({
@@ -108267,7 +108383,7 @@ var languages = [
108267
108383
  "jinja2"
108268
108384
  ],
108269
108385
  load() {
108270
- return import("./dist-CRw-jyve.js").then((m) => m.jinja());
108386
+ return import("./dist-DoPtyXvU.js").then((m) => m.jinja());
108271
108387
  }
108272
108388
  }),
108273
108389
  /* @__PURE__ */ LanguageDescription.of({
@@ -108275,7 +108391,7 @@ var languages = [
108275
108391
  alias: ["json5"],
108276
108392
  extensions: ["json", "map"],
108277
108393
  load() {
108278
- return import("./dist-D2ilXjzO.js").then((m) => m.json());
108394
+ return import("./dist-DhIAeIAf.js").then((m) => m.json());
108279
108395
  }
108280
108396
  }),
108281
108397
  /* @__PURE__ */ LanguageDescription.of({
@@ -108289,14 +108405,14 @@ var languages = [
108289
108405
  name: "LESS",
108290
108406
  extensions: ["less"],
108291
108407
  load() {
108292
- return import("./dist-C8mczL_o.js").then((m) => m.less());
108408
+ return import("./dist-CeAwBeY0.js").then((m) => m.less());
108293
108409
  }
108294
108410
  }),
108295
108411
  /* @__PURE__ */ LanguageDescription.of({
108296
108412
  name: "Liquid",
108297
108413
  extensions: ["liquid"],
108298
108414
  load() {
108299
- return import("./dist-CmE7gK9r.js").then((m) => m.liquid());
108415
+ return import("./dist-C8tud7al.js").then((m) => m.liquid());
108300
108416
  }
108301
108417
  }),
108302
108418
  /* @__PURE__ */ LanguageDescription.of({
@@ -108313,7 +108429,7 @@ var languages = [
108313
108429
  "mkd"
108314
108430
  ],
108315
108431
  load() {
108316
- return import("./dist-Bk9be2-W.js").then((m) => m.markdown());
108432
+ return import("./dist-DVq3OitZ.js").then((m) => m.markdown());
108317
108433
  }
108318
108434
  }),
108319
108435
  /* @__PURE__ */ LanguageDescription.of({
@@ -108339,7 +108455,7 @@ var languages = [
108339
108455
  "phtml"
108340
108456
  ],
108341
108457
  load() {
108342
- return import("./dist-QLG95fVW.js").then((m) => m.php());
108458
+ return import("./dist-BuA1hNQD.js").then((m) => m.php());
108343
108459
  }
108344
108460
  }),
108345
108461
  /* @__PURE__ */ LanguageDescription.of({
@@ -108379,14 +108495,14 @@ var languages = [
108379
108495
  name: "Sass",
108380
108496
  extensions: ["sass"],
108381
108497
  load() {
108382
- return import("./dist-D3Ubfaie.js").then((m) => m.sass({ indented: true }));
108498
+ return import("./dist-uLS_wgVI.js").then((m) => m.sass({ indented: true }));
108383
108499
  }
108384
108500
  }),
108385
108501
  /* @__PURE__ */ LanguageDescription.of({
108386
108502
  name: "SCSS",
108387
108503
  extensions: ["scss"],
108388
108504
  load() {
108389
- return import("./dist-D3Ubfaie.js").then((m) => m.sass());
108505
+ return import("./dist-uLS_wgVI.js").then((m) => m.sass());
108390
108506
  }
108391
108507
  }),
108392
108508
  /* @__PURE__ */ LanguageDescription.of({
@@ -108453,7 +108569,7 @@ var languages = [
108453
108569
  alias: ["yml"],
108454
108570
  extensions: ["yaml", "yml"],
108455
108571
  load() {
108456
- return import("./dist-DbHDr3r9.js").then((m) => m.yaml());
108572
+ return import("./dist-DQfK_0MA.js").then((m) => m.yaml());
108457
108573
  }
108458
108574
  }),
108459
108575
  /* @__PURE__ */ LanguageDescription.of({
@@ -109340,13 +109456,13 @@ var languages = [
109340
109456
  name: "Vue",
109341
109457
  extensions: ["vue"],
109342
109458
  load() {
109343
- return import("./dist-A6g9ScYS.js").then((m) => m.vue());
109459
+ return import("./dist-cd39lbM_.js").then((m) => m.vue());
109344
109460
  }
109345
109461
  }),
109346
109462
  /* @__PURE__ */ LanguageDescription.of({
109347
109463
  name: "Angular Template",
109348
109464
  load() {
109349
- return import("./dist-DHhdkqG1.js").then((m) => m.angular());
109465
+ return import("./dist-BrgApT3v.js").then((m) => m.angular());
109350
109466
  }
109351
109467
  })
109352
109468
  ];
@@ -152720,6 +152836,33 @@ var { codeToHtml, codeToHast, codeToTokens, codeToTokensBase, codeToTokensWithTh
152720
152836
  engine: () => createOnigurumaEngine(import("./wasm-CzpHWGSE.js"))
152721
152837
  }), { guessEmbeddedLanguages });
152722
152838
  //#endregion
152839
+ //#region src/lib/remark-cli-task-parity.ts
152840
+ /**
152841
+ * Box prefix of a CLI 1.13.1 task line: at most one non-`]`/non-whitespace token
152842
+ * (optionally padded with whitespace) or a whitespace-only box. Mirrors
152843
+ * references/openspec/src/utils/task-progress.ts (pinned v1.13.1); the marker and
152844
+ * indentation are already consumed by list parsing, and links parse into link nodes
152845
+ * (never leading text), so the CLI's link-continuation guard holds structurally.
152846
+ */
152847
+ var CLI_TASK_BOX_PREFIX = /^\[(?:\s*([^\]\s]?)\s*\]|\s+\])(?=\s|$)/;
152848
+ /**
152849
+ * Mark unrecognized widened-form list items as task items with the CLI completion
152850
+ * semantics. GFM-recognized items (checked already set) are left untouched.
152851
+ */
152852
+ var remarkCliTaskParity = () => (tree) => {
152853
+ visit(tree, "listItem", (node) => {
152854
+ const item = node;
152855
+ if (item.checked !== null && item.checked !== void 0) return;
152856
+ const first = item.children.find((child) => child.type === "paragraph")?.children[0];
152857
+ if (!first || first.type !== "text") return;
152858
+ const text = first;
152859
+ const match = CLI_TASK_BOX_PREFIX.exec(text.value);
152860
+ if (!match) return;
152861
+ item.checked = (match[1] ?? "").toLowerCase() === "x";
152862
+ text.value = text.value.slice(match[0].length);
152863
+ });
152864
+ };
152865
+ //#endregion
152723
152866
  //#region src/components/markdown-content.tsx
152724
152867
  /**
152725
152868
  * Simple markdown renderer with GFM support and shiki code highlighting.
@@ -152732,7 +152875,7 @@ function MarkdownContent({ children, className = "", components, hastProcessors
152732
152875
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
152733
152876
  className: `markdown-content ${className}`,
152734
152877
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Markdown, {
152735
- remarkPlugins: [remarkGfm],
152878
+ remarkPlugins: [remarkGfm, remarkCliTaskParity],
152736
152879
  rehypePlugins,
152737
152880
  components: {
152738
152881
  ...annotationComponents,
@@ -169628,6 +169771,36 @@ function ReadonlyKanbanRow({ item, laneId, compact }) {
169628
169771
  });
169629
169772
  }
169630
169773
  //#endregion
169774
+ //#region src/lib/change-display-title.ts
169775
+ /**
169776
+ * Orthogonal intents (created 2026-09-12 Asia/Shanghai):
169777
+ * 1. Derive one shared display title for a Change across list, dashboard, and detail surfaces.
169778
+ * 2. Treat the proposal H1 as a human-readable title only when it is informative.
169779
+ * 3. Fall back to the change id (the CLI's own canonical name) otherwise.
169780
+ *
169781
+ * Original request (2026-09-12): Owner walkthrough: the Changes list showed the generic proposal
169782
+ * heading "Proposal" as the row title while Change Detail showed the change id — unify the scheme.
169783
+ */
169784
+ /**
169785
+ * Heading texts that carry no identity information. `openspec new change` scaffolds proposals with
169786
+ * the bare heading "# Proposal"; showing it as a row title reads as a parsing bug rather than a name.
169787
+ */
169788
+ var GENERIC_PROPOSAL_HEADINGS = new Set(["proposal"]);
169789
+ /**
169790
+ * One display title for a Change, identical on every surface.
169791
+ *
169792
+ * `name` is the legacy parser's proposal H1 (absent for parser-less custom schemas); the change id
169793
+ * is the CLI-owned canonical identity (`openspec list --json` names changes by directory). The H1
169794
+ * wins only when it is a real, differentiated title; generic headings and the id itself fall back
169795
+ * to the id, so no surface ever shows two different titles for the same Change.
169796
+ */
169797
+ function changeDisplayTitle(changeId, name) {
169798
+ const trimmed = name?.trim();
169799
+ if (!trimmed || trimmed === changeId) return changeId;
169800
+ if (GENERIC_PROPOSAL_HEADINGS.has(trimmed.toLowerCase())) return changeId;
169801
+ return trimmed;
169802
+ }
169803
+ //#endregion
169631
169804
  //#region src/lib/opsx-compose.ts
169632
169805
  var ACTION_QUERY_KEY = "action";
169633
169806
  var CHANGE_QUERY_KEY = "change";
@@ -169856,15 +170029,18 @@ function useChangeOperatorLauncher({ applyCurrent = true, archiveCurrent = true
169856
170029
  //#endregion
169857
170030
  //#region src/routes/board.tsx
169858
170031
  /**
169859
- * Orthogonal intents (updated 2026-07-28 Asia/Shanghai):
170032
+ * Orthogonal intents (updated 2026-09-18 Asia/Shanghai):
169860
170033
  * 1. Compose live Changes and Archives as independent objective Kanban regions.
169861
170034
  * 2. Bind live commands to shared Change Operators and current projection authority.
169862
170035
  * 3. Render static Board through the shared readonly presentation and archive range policy.
169863
170036
  * 4. Bound the live route to the shell block-size and contain competing page overflow.
170037
+ * 5. Normalize card titles through the shared changeDisplayTitle fallback.
169864
170038
  *
169865
170039
  * Contributor request (2026-07-18): add a Kanban-style Change view.
169866
170040
  * Owner decision (2026-07-28): implement objective OPSX lanes and shared Operator ownership.
169867
170041
  * Owner correction (2026-07-28): prevent competing horizontal scrollbars on narrow `/board`.
170042
+ * Original request (2026-09-18): owner walkthrough Case 5 — every Kanban card showed the
170043
+ * generic scaffold heading "Proposal"; Board never received the display-title fallback.
169868
170044
  */
169869
170045
  var RANGE_OPTIONS = [
169870
170046
  {
@@ -169890,8 +170066,14 @@ function Board() {
169890
170066
  const archivesState = useArchivesSubscription();
169891
170067
  const statusState = useOpsxStatusListSubscription(!staticMode);
169892
170068
  const [range, setRange] = (0, import_react.useState)("30d");
169893
- const activeItems = changesState.data ?? [];
169894
- const archivedItems = (0, import_react.useMemo)(() => filterKanbanArchives(archivesState.data ?? [], range), [archivesState.data, range]);
170069
+ const activeItems = (0, import_react.useMemo)(() => (changesState.data ?? []).map((change) => ({
170070
+ ...change,
170071
+ name: changeDisplayTitle(change.id, change.name)
170072
+ })), [changesState.data]);
170073
+ const archivedItems = (0, import_react.useMemo)(() => filterKanbanArchives(archivesState.data ?? [], range).map((archive) => ({
170074
+ ...archive,
170075
+ name: changeDisplayTitle(archive.id, archive.name)
170076
+ })), [archivesState.data, range]);
169895
170077
  const activeCurrent = changesState.data !== void 0 && !changesState.isLoading && !changesState.isUpdating && changesState.error === null;
169896
170078
  const archiveCurrent = archivesState.data !== void 0 && !archivesState.isLoading && !archivesState.isUpdating && archivesState.error === null;
169897
170079
  const applyStatusCurrent = statusState.data !== void 0 && statusState.authority.state === "current";
@@ -170171,6 +170353,8 @@ function useChangeListContinuity(incomingChanges, containerRef) {
170171
170353
  * 3. Preserve ChangeList row continuity and stale display together with collision-safe detail navigation.
170172
170354
  * 4. Keep the advanced New Change command reachable from the page header.
170173
170355
  * 5. Defer aggregate workflow Status until a primary Change row is renderable; preserve explicit failures.
170356
+ * 6. Render OpenSpec 1.13.1 change-list hygiene warnings on the direct plane without ever
170357
+ * turning a namespace directory into a row, task summary, or detail navigation target.
170174
170358
  *
170175
170359
  * Original request (2026-07-23): "现在页面数据的加载数据非常慢(比如dashboard页面、changes页面都要等待非常久,页面刷新后,似乎后台没有缓存一样,也要加载很久。"
170176
170360
  * Original request (2026-07-23): "List mutations and route changes preserve physical continuity through existing motion/View Transition patterns."
@@ -170180,16 +170364,73 @@ function useChangeListContinuity(incomingChanges, containerRef) {
170180
170364
  * Original request (2026-07-21): "Changes页面的右上角没有 New,你要不要快速补一个"
170181
170365
 
170182
170366
  * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
170367
+ * Original request (2026-09-12): Owner walkthrough: unify the Change display title — generic
170368
+ * "# Proposal" headings fall back to the change id on every surface.
170369
+ * Original request (2026-09-17): "Openspec 1.13.1 释放了…" — change-list nested/warnings projection (update-openspec-cli-1131 Slice 2).
170183
170370
  */
170184
170371
  function buildStatusMap(statuses) {
170185
170372
  return new Map((statuses ?? []).map((status) => [status.changeName, status]));
170186
170373
  }
170374
+ /** Known OpenSpec 1.13.1 warning codes; every other code renders the generic fallback. */
170375
+ var CHANGE_LIST_WARNING_CODE_LABELS = { nested_change_directory: "Nested change directory" };
170376
+ function changeListWarningLabel(code) {
170377
+ return CHANGE_LIST_WARNING_CODE_LABELS[code] ?? "Change list hygiene warning";
170378
+ }
170379
+ /**
170380
+ * OpenSpec 1.13.1 hygiene warnings on the direct plane: the namespace directory, its
170381
+ * nested change names, and the upstream message verbatim. Display evidence only — no row,
170382
+ * no task summary, no detail-route link, and no read/write/repair attempt on the wrapped
170383
+ * directories (the CLI owns that message; OpenSpecUI only surfaces it).
170384
+ */
170385
+ function ChangeListHygieneWarnings({ warnings }) {
170386
+ if (warnings.length === 0) return null;
170387
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
170388
+ "data-change-list-warnings": true,
170389
+ role: "note",
170390
+ className: "space-y-2 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm text-amber-800 dark:text-amber-200",
170391
+ children: warnings.map((warning) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
170392
+ className: "flex items-start gap-2",
170393
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
170394
+ className: "mt-0.5 h-4 w-4 shrink-0",
170395
+ "aria-hidden": true
170396
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
170397
+ className: "min-w-0",
170398
+ children: [
170399
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
170400
+ className: "font-medium",
170401
+ children: changeListWarningLabel(warning.code)
170402
+ }),
170403
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
170404
+ className: "text-muted-foreground",
170405
+ children: " · "
170406
+ }),
170407
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
170408
+ className: "break-all font-mono text-xs",
170409
+ children: warning.name
170410
+ }),
170411
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
170412
+ className: "text-muted-foreground text-xs",
170413
+ children: ["wraps ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
170414
+ className: "break-all font-mono",
170415
+ children: warning.nested.join(", ")
170416
+ })]
170417
+ }),
170418
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
170419
+ className: "mt-1 break-words text-xs",
170420
+ children: warning.message
170421
+ })
170422
+ ]
170423
+ })]
170424
+ }, `${warning.code}:${warning.name}`))
170425
+ });
170426
+ }
170187
170427
  function ChangeList() {
170188
170428
  const { data: changes, isLoading, isUpdating, error: changesError, rowErrors = [], progress = null } = useChangesSubscription();
170189
170429
  const listRef = (0, import_react.useRef)(null);
170190
170430
  const { data: statuses, isLoading: isStatusLoading, error: statusError } = useOpsxStatusListSubscription((changes?.length ?? 0) > 0);
170191
170431
  const displayedChanges = useChangeListContinuity(changes, listRef);
170192
170432
  const statusMap = buildStatusMap(statuses);
170433
+ const { data: hygieneWarnings } = useOpsxChangeListHygieneWarningsSubscription();
170193
170434
  const hasCurrentEmptyChanges = changes?.length === 0 && !changesError && !isUpdating;
170194
170435
  const showChangesFrame = (changes?.length ?? 0) > 0 || hasCurrentEmptyChanges;
170195
170436
  if (isLoading && !changes && !changesError) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -170244,6 +170485,7 @@ function ChangeList() {
170244
170485
  "."
170245
170486
  ]
170246
170487
  }),
170488
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeListHygieneWarnings, { warnings: hygieneWarnings ?? [] }),
170247
170489
  changesError ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
170248
170490
  role: "alert",
170249
170491
  className: "border-destructive/40 bg-destructive/10 text-destructive flex items-center gap-2 rounded-md border px-3 py-2 text-sm",
@@ -170329,7 +170571,7 @@ function ChangeList() {
170329
170571
  __vtHandoff: {
170330
170572
  family: "changes",
170331
170573
  entityId: change.id,
170332
- title: change.name,
170574
+ title: changeDisplayTitle(change.id, change.name),
170333
170575
  subtitle: change.id
170334
170576
  }
170335
170577
  }),
@@ -170340,7 +170582,7 @@ function ChangeList() {
170340
170582
  className: "flex items-center gap-3",
170341
170583
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeRow, {
170342
170584
  changeId: change.id,
170343
- name: change.name,
170585
+ name: changeDisplayTitle(change.id, change.name),
170344
170586
  phase,
170345
170587
  updatedAt: change.updatedAt,
170346
170588
  formatTime: formatRelativeTime,
@@ -171386,16 +171628,27 @@ function EvidenceDisclosure({ title, children, summary, defaultOpen = false, cla
171386
171628
  //#endregion
171387
171629
  //#region src/components/apply-progress-notice.tsx
171388
171630
  /**
171389
- * Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
171631
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
171390
171632
  * 1. Attribute Apply instruction counts to the upstream Apply command.
171391
171633
  * 2. Compress agreement to one subtitle badge; keep divergence a direct blocker.
171392
171634
  * 3. Keep divergence's two objective source counts side by side with their causes.
171393
171635
  * 4. Keep tooltips as the keyboard-reachable explanation for every compact count.
171636
+ * 5. Render OpenSpec 1.13 Apply `warnings`/`missingPrerequisites` as ONE always-visible summary
171637
+ * row (count + build-order chain, CLI attribution) whose verbatim evidence is one explicit
171638
+ * expansion away on the same direct plane — advisory guidance must stay discoverable without
171639
+ * consuming the page; a Tooltip-only surface remains forbidden.
171640
+ * 6. Keep `missingPrerequisites` visually and semantically distinct from blockers (status
171641
+ * semantics), including when the Apply state is already `ready`.
171642
+ * 7. Degrade to the previous presentation when either 1.13 field is absent — absent keys
171643
+ * are the upstream encoding for "none", so no empty state is ever synthesized.
171394
171644
  *
171395
171645
  * Original request (2026-07-15): "与 tracked glob 进度分歧时各自归因展示。"
171396
171646
  * Original request (2026-07-28): supporting 6.x evidence should use Badge + Tooltip or Accordion.
171397
171647
  * Original request (2026-08-15): Owner walkthrough: agreement is one badge in the subtitle row,
171398
171648
  * not a two-line block; only divergence owns a notice.
171649
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
171650
+ * Original request (2026-09-12): Owner walkthrough: the always-expanded warning/build-order blocks
171651
+ * consumed the page; collapse them behind one summary row while keeping direct-plane discovery.
171399
171652
  */
171400
171653
  /**
171401
171654
  * One compact, source-attributed Apply progress badge for the Change subtitle row.
@@ -171416,54 +171669,143 @@ function ApplyProgressBadge({ applyInstructionProgress }) {
171416
171669
  ]
171417
171670
  });
171418
171671
  }
171672
+ /** Upstream command that owns every fact rendered by these notices. */
171673
+ var APPLY_COMMAND_ATTRIBUTION = "openspec instructions apply";
171674
+ var GUIDANCE_DETAIL_ID = "apply-readiness-guidance-detail";
171419
171675
  /**
171420
- * Render the Apply/tracked divergence as one direct, source-attributed blocker. Returns
171421
- * null when the sources agree — the agreement case lives in the subtitle badge row via
171422
- * {@link ApplyProgressBadge}.
171676
+ * Render the Apply/tracked divergence as one direct, source-attributed blocker, plus the
171677
+ * OpenSpec 1.13 `warnings` and `missingPrerequisites` evidence as one collapsible summary row:
171678
+ * the row itself names the warning count and the build-order chain (discovery needs no hover),
171679
+ * and expanding reveals the verbatim upstream evidence on the same direct plane.
171680
+ * Returns null when none apply — the agreement case lives in the subtitle badge row via
171681
+ * {@link ApplyProgressBadge}, and absent 1.13 keys render nothing.
171423
171682
  */
171424
- function ApplyProgressNotice({ applyInstructionProgress }) {
171683
+ function ApplyProgressNotice({ applyInstructionProgress, warnings, missingPrerequisites }) {
171425
171684
  const divergence = applyInstructionProgress.divergence;
171426
- if (!divergence) return null;
171427
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171428
- role: "status",
171429
- "aria-label": "Task progress source divergence",
171430
- className: "flex min-w-0 items-start gap-2 border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-950 dark:border-amber-700 dark:bg-amber-950/40 dark:text-amber-100",
171431
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
171432
- className: "mt-0.5 h-4 w-4 shrink-0",
171433
- "aria-hidden": "true"
171434
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171435
- className: "min-w-0 space-y-2",
171685
+ const hasWarnings = (warnings?.length ?? 0) > 0;
171686
+ const hasPrerequisites = (missingPrerequisites?.length ?? 0) > 0;
171687
+ const [expanded, setExpanded] = (0, import_react.useState)(false);
171688
+ if (!divergence && !hasWarnings && !hasPrerequisites) return null;
171689
+ const guidanceSummaryParts = [];
171690
+ if (hasWarnings) {
171691
+ const count = warnings.length;
171692
+ guidanceSummaryParts.push(`${count} apply warning${count > 1 ? "s" : ""}`);
171693
+ }
171694
+ if (hasPrerequisites) guidanceSummaryParts.push(`next in build order: ${missingPrerequisites.join(" → ")}`);
171695
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
171696
+ hasWarnings || hasPrerequisites ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171697
+ role: "status",
171698
+ "data-apply-notice": "summary",
171699
+ "aria-label": `Apply readiness guidance from ${APPLY_COMMAND_ATTRIBUTION}`,
171700
+ className: hasWarnings ? "flex min-w-0 items-center gap-2 border border-amber-300 bg-amber-50 px-3 py-1.5 text-xs text-amber-950 dark:border-amber-700 dark:bg-amber-950/40 dark:text-amber-100" : "text-muted-foreground flex min-w-0 items-center gap-2 rounded-md border px-3 py-1.5 text-xs",
171436
171701
  children: [
171437
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171438
- className: "font-medium",
171439
- children: "Upstream task progress divergence"
171702
+ hasWarnings ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
171703
+ className: "h-4 w-4 shrink-0",
171704
+ "aria-hidden": "true"
171705
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ListOrdered, {
171706
+ className: "h-4 w-4 shrink-0",
171707
+ "aria-hidden": "true"
171440
171708
  }),
171441
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: divergence.message }),
171442
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171443
- className: "flex flex-wrap gap-1.5",
171444
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171445
- ariaLabel: `Apply instructions progress ${applyInstructionProgress.complete} of ${applyInstructionProgress.total}`,
171446
- tooltip: "Progress reported by openspec instructions apply.",
171447
- children: [
171448
- "Apply ",
171449
- applyInstructionProgress.complete,
171450
- "/",
171451
- applyInstructionProgress.total
171452
- ]
171453
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171454
- ariaLabel: `Tracked artifact glob progress ${divergence.tracked.completed} of ${divergence.tracked.total}`,
171455
- tooltip: "Progress computed from the workflow's tracked task artifact glob.",
171456
- children: [
171457
- "Tracked ",
171458
- divergence.tracked.completed,
171459
- "/",
171460
- divergence.tracked.total
171461
- ]
171709
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
171710
+ type: "button",
171711
+ onClick: () => setExpanded((value) => !value),
171712
+ "aria-expanded": expanded,
171713
+ "aria-controls": GUIDANCE_DETAIL_ID,
171714
+ className: "flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-left",
171715
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
171716
+ className: "truncate font-medium",
171717
+ children: guidanceSummaryParts.join(" · ")
171718
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
171719
+ className: "text-muted-foreground shrink-0 font-normal",
171720
+ children: ["— ", APPLY_COMMAND_ATTRIBUTION]
171462
171721
  })]
171722
+ }),
171723
+ expanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {
171724
+ className: "h-4 w-4 shrink-0",
171725
+ "aria-hidden": "true"
171726
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, {
171727
+ className: "h-4 w-4 shrink-0",
171728
+ "aria-hidden": "true"
171463
171729
  })
171464
171730
  ]
171465
- })]
171466
- });
171731
+ }) : null,
171732
+ expanded && (hasWarnings || hasPrerequisites) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171733
+ id: GUIDANCE_DETAIL_ID,
171734
+ className: "text-muted-foreground space-y-2 rounded-md border px-3 py-2 text-xs",
171735
+ children: [hasWarnings ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171736
+ "data-apply-notice": "warnings",
171737
+ className: "min-w-0 space-y-1",
171738
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171739
+ className: "text-foreground font-medium",
171740
+ children: ["Apply warnings — reported by ", APPLY_COMMAND_ATTRIBUTION]
171741
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", {
171742
+ className: "space-y-1",
171743
+ children: warnings?.map((warning) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", {
171744
+ className: "break-words",
171745
+ children: warning
171746
+ }, warning))
171747
+ })]
171748
+ }) : null, hasPrerequisites ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171749
+ "data-apply-notice": "build-order",
171750
+ className: "min-w-0 space-y-1",
171751
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171752
+ className: "text-foreground font-medium",
171753
+ children: ["Next in build order — reported by ", APPLY_COMMAND_ATTRIBUTION]
171754
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171755
+ className: "flex flex-wrap items-center gap-1",
171756
+ children: missingPrerequisites?.map((artifactId, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
171757
+ className: "text-muted-foreground/70",
171758
+ "aria-hidden": "true",
171759
+ children: "→"
171760
+ }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
171761
+ className: "bg-muted break-words rounded border px-1 py-0.5 font-mono [overflow-wrap:anywhere]",
171762
+ children: artifactId
171763
+ })] }, artifactId))
171764
+ })]
171765
+ }) : null]
171766
+ }) : null,
171767
+ divergence ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171768
+ role: "status",
171769
+ "data-apply-notice": "divergence",
171770
+ "aria-label": "Task progress source divergence",
171771
+ className: "flex min-w-0 items-start gap-2 border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-950 dark:border-amber-700 dark:bg-amber-950/40 dark:text-amber-100",
171772
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
171773
+ className: "mt-0.5 h-4 w-4 shrink-0",
171774
+ "aria-hidden": "true"
171775
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171776
+ className: "min-w-0 space-y-2",
171777
+ children: [
171778
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
171779
+ className: "font-medium",
171780
+ children: "Upstream task progress divergence"
171781
+ }),
171782
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: divergence.message }),
171783
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
171784
+ className: "flex flex-wrap gap-1.5",
171785
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171786
+ ariaLabel: `Apply instructions progress ${applyInstructionProgress.complete} of ${applyInstructionProgress.total}`,
171787
+ tooltip: "Progress reported by openspec instructions apply.",
171788
+ children: [
171789
+ "Apply ",
171790
+ applyInstructionProgress.complete,
171791
+ "/",
171792
+ applyInstructionProgress.total
171793
+ ]
171794
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InformationBadge, {
171795
+ ariaLabel: `Tracked artifact glob progress ${divergence.tracked.completed} of ${divergence.tracked.total}`,
171796
+ tooltip: "Progress computed from the workflow's tracked task artifact glob.",
171797
+ children: [
171798
+ "Tracked ",
171799
+ divergence.tracked.completed,
171800
+ "/",
171801
+ divergence.tracked.total
171802
+ ]
171803
+ })]
171804
+ })
171805
+ ]
171806
+ })]
171807
+ }) : null
171808
+ ] });
171467
171809
  }
171468
171810
  //#endregion
171469
171811
  //#region src/components/change-context-summary.tsx
@@ -171598,16 +171940,16 @@ function EvidenceLayerHeader({ title, summary }) {
171598
171940
  }
171599
171941
  //#endregion
171600
171942
  //#region ../core/src/openspec-compat.ts
171601
- var OPENSPEC_CLI_TARGET_SERIES = "1.12";
171602
- var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.12"];
171603
- var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.12.0 <1.13.0";
171943
+ var OPENSPEC_CLI_TARGET_SERIES = "1.13";
171944
+ var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.13"];
171945
+ var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.13.0 <1.14.0";
171604
171946
  /**
171605
171947
  * Derive command capabilities from one parsed CLI version.
171606
171948
  *
171607
171949
  * Only an admitted version — stable inside the accepted range — can select version-specific
171608
- * capabilities. Unsupported forms (prereleases, >=1.13, below-range) and unparseable output
171950
+ * capabilities. Unsupported forms (prereleases, >=1.14, below-range) and unparseable output
171609
171951
  * keep their mismatch evidence and expose no capability, so a page-level version bypass can
171610
- * never manufacture a 1.12 command surface for a CLI the release line does not admit.
171952
+ * never manufacture a 1.13 command surface for a CLI the release line does not admit.
171611
171953
  */
171612
171954
  function deriveOpenSpecCliCapabilities(version) {
171613
171955
  if (!isAdmittedVersion(version)) return {
@@ -171649,7 +171991,7 @@ function isStable(version) {
171649
171991
  /** True only for stable versions inside the accepted range (current or supported non-current). */
171650
171992
  function isAdmittedVersion(version) {
171651
171993
  if (!version || !isStable(version)) return false;
171652
- return isSeries(version, "1.12") || isSupportedNonCurrentSeries(version);
171994
+ return isSeries(version, "1.13") || isSupportedNonCurrentSeries(version);
171653
171995
  }
171654
171996
  function isSupportedNonCurrentSeries(version) {
171655
171997
  return OPENSPEC_CLI_SUPPORTED_SERIES.filter((series) => series !== OPENSPEC_CLI_TARGET_SERIES).some((series) => isSeries(version, series));
@@ -171657,11 +171999,11 @@ function isSupportedNonCurrentSeries(version) {
171657
171999
  //#endregion
171658
172000
  //#region src/components/archived-validation-evidence.tsx
171659
172001
  /**
171660
- * Orthogonal intents (updated 2026-09-03 Asia/Shanghai):
172002
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
171661
172003
  * 1. Present OpenSpec `validate --archived --json` as typed CLI evidence.
171662
172004
  * 2. Preserve item issues, totals, root, and exit/failure evidence without repair actions.
171663
172005
  * 3. Identify the evidence as unavailable in static snapshots instead of fabricating it.
171664
- * 4. Derive the capability from the detected admitted CLI; the admitted 1.12 line declares
172006
+ * 4. Derive the capability from the detected admitted CLI; the admitted 1.13 line declares
171665
172007
  * it, so the unavailable branch names the accepted range, not one series.
171666
172008
  * 5. Validate report payloads with the Core contract schema, never shallow shape guards.
171667
172009
  * 6. Mount directly inside the Evidence workspace detail pane: the Accordion shell is gone, the
@@ -171673,6 +172015,7 @@ function isSupportedNonCurrentSeries(version) {
171673
172015
  * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
171674
172016
  * Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
171675
172017
  * Owner walkthrough correction (2026-09-04): every Evidence detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding); this replaces each layer's local weak header.
172018
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
171676
172019
  */
171677
172020
  function parseValidationReport$1(value) {
171678
172021
  const parsed = CliValidateReportSchema.safeParse(value);
@@ -172566,8 +172909,9 @@ function EvidenceList({ label, values }) {
172566
172909
  //#endregion
172567
172910
  //#region src/components/validation-findings-evidence.tsx
172568
172911
  /**
172569
- * Orthogonal intents (updated 2026-09-04 Asia/Shanghai):
172570
- * 1. Present the OpenSpec 1.12 `validate --report findings` document as typed CLI evidence.
172912
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
172913
+ * 1. Present the OpenSpec 1.12+ `validate --report findings` document (the admitted 1.13
172914
+ * line carries the capability) as typed CLI evidence.
172571
172915
  * 2. Attribute every item finding to its owning change: entries owned by the current change
172572
172916
  * render as the primary "This change" list, while entries owned by other active changes
172573
172917
  * stay in a clearly-labeled secondary disclosure with prominent change attribution — a
@@ -172583,6 +172927,7 @@ function EvidenceList({ label, values }) {
172583
172927
  *
172584
172928
  * Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
172585
172929
  * Owner walkthrough correction (2026-09-04): findings must attribute their owning change; the Evidence detail panel styling follows the vision review and every detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding) instead of a local weak header.
172930
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
172586
172931
  */
172587
172932
  function parseFindingsPayload(value) {
172588
172933
  const parsed = CliValidateFindingsResultSchema.safeParse(value);
@@ -173060,6 +173405,7 @@ function ValidationFindingsEvidence({ changeId, onChip }) {
173060
173405
  * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
173061
173406
  * Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进"
173062
173407
  * Owner walkthrough correction (2026-09-04): findings must attribute their owning change; the Evidence detail panel styling follows the vision review and every detail layer renders the shared EvidenceLayerHeader contract (title dominant over body, house-standard border padding) instead of a local weak header.
173408
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
173063
173409
  */
173064
173410
  /**
173065
173411
  * Spacious threshold: below this inline size the workspace collapses to one column and the
@@ -173510,13 +173856,14 @@ function RootActionNotice({ state }) {
173510
173856
  //#endregion
173511
173857
  //#region src/routes/change-view.tsx
173512
173858
  /**
173513
- * Orthogonal intents (updated 2026-08-28 Asia/Shanghai):
173859
+ * Orthogonal intents (updated 2026-09-12 Asia/Shanghai):
173514
173860
  * 1. Render schema-aware change artifacts and source files while retaining terminal status errors.
173515
173861
  * 2. Dispatch change workflows through routed compose/verify surfaces and the shared Operator launcher.
173516
173862
  * 3. Lock every change workflow action behind current Root Context and Status projection authority.
173517
173863
  * 4. Present Apply progress directly and expose project context/guidance through a Header Action Dialog.
173518
173864
  * 5. Keep compact Change facts in subtitle badges while routing complete CLI evidence through a dedicated tab.
173519
173865
  * 6. Mount the container-responsive list-detail Evidence workspace as the sole Evidence tab surface.
173866
+ * 7. Mount OpenSpec 1.13 Apply warnings and the build-order chain on the direct status plane.
173520
173867
  *
173521
173868
  * Original request (2026-07-15): "Root-dependent actions remain locked until root selection succeeds."
173522
173869
  * Review request (2026-07-23): "代码已经提交,开始review。如果有问题,那么可更新change。"
@@ -173529,6 +173876,11 @@ function RootActionNotice({ state }) {
173529
173876
  * tab gains the capability-gated CLI MODIFIED-delta diff evidence beside the existing layers.
173530
173877
  * Original request (2026-09-03): "Openspec 1.12.0 刚刚放出来,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进" — the Evidence tab gains the findings evidence section.
173531
173878
  * Original request (2026-08-28): "使用移动端的 list-detail 思维……分成两栏,左侧 list,右侧详情。这种结构替代手风琴会更好"
173879
+ * Original request (2026-09-12): "Openspec 1.13.0 释放了,你更新一下,调查变更内容,然后开始规划适配工作,我们将用标准工作流worktree来推进。让 codex 参与。"
173880
+ * Original request (2026-09-12): Owner walkthrough: unify the Change display title (generic "# Proposal"
173881
+ * headings fall back to the change id) and collapse Apply readiness guidance into one summary row.
173882
+ * — the status region gains the OpenSpec 1.13 Apply `warnings` and `missingPrerequisites`
173883
+ * direct-plane evidence beside the existing divergence notice.
173532
173884
  */
173533
173885
  function ChangeView() {
173534
173886
  const { changeId } = useParams({ from: "/changes/$changeId" });
@@ -173539,6 +173891,8 @@ function ChangeView() {
173539
173891
  const { data: status, isLoading, error } = statusProjection;
173540
173892
  const { data: applyInstructions } = useOpsxApplyInstructionsSubscription({ change: changeId });
173541
173893
  const { data: files } = useChangeFilesSubscription(changeId);
173894
+ const changesRows = useChangesSubscription().data;
173895
+ const displayTitle = changeDisplayTitle(changeId, changesRows?.find((row) => row.id === changeId)?.name ?? status?.changeName);
173542
173896
  const handleComposeAction = (0, import_react.useCallback)((actionId, artifactId) => {
173543
173897
  if (actionId === "apply") {
173544
173898
  launchApply({
@@ -173609,14 +173963,14 @@ function ChangeView() {
173609
173963
  })
173610
173964
  }] : [], [referenceEvidence, status]);
173611
173965
  const hasReferenceFailures = referenceEvidence.state !== "unavailable" && referenceEvidence.references.some((reference) => reference.status.some((diagnostic) => diagnostic.severity === "error"));
173612
- const hasDirectStatus = Boolean(error) || rootAction.status === "blocked" || hasReferenceFailures || Boolean(applyInstructions?.applyInstructionProgress.divergence);
173966
+ const hasDirectStatus = Boolean(error) || rootAction.status === "blocked" || hasReferenceFailures || Boolean(applyInstructions?.applyInstructionProgress.divergence) || (applyInstructions?.warnings?.length ?? 0) > 0 || (applyInstructions?.missingPrerequisites?.length ?? 0) > 0;
173613
173967
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OpsxEntityDetailView, {
173614
173968
  entityId: changeId,
173615
173969
  sharedFamily: "changes",
173616
173970
  backTo: "/changes",
173617
173971
  backTitle: "Back to Changes",
173618
173972
  icon: GitBranch,
173619
- title: status?.changeName,
173973
+ title: displayTitle,
173620
173974
  subtitle: status ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeContextSummary, {
173621
173975
  status,
173622
173976
  referenceEvidence,
@@ -173684,7 +174038,11 @@ function ChangeView() {
173684
174038
  }) : null,
173685
174039
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RootActionNotice, { state: rootAction }),
173686
174040
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeReferenceFailureNotice, { referenceEvidence }),
173687
- applyInstructions ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApplyProgressNotice, { applyInstructionProgress: applyInstructions.applyInstructionProgress }) : null
174041
+ applyInstructions ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ApplyProgressNotice, {
174042
+ applyInstructionProgress: applyInstructions.applyInstructionProgress,
174043
+ warnings: applyInstructions.warnings,
174044
+ missingPrerequisites: applyInstructions.missingPrerequisites
174045
+ }) : null
173688
174046
  ]
173689
174047
  }) : null
173690
174048
  });
@@ -173724,7 +174082,7 @@ var CONFIG_GUIDE_STAGE_META = {
173724
174082
  //#region src/components/config/config-guide.tsx
173725
174083
  var ConfigGuideContext = (0, import_react.createContext)(null);
173726
174084
  (0, import_react.lazy)(async () => {
173727
- return { default: (await import("./config-guide-presentation-GWnVFKTW.js")).ConfigGuidePresentationLayer };
174085
+ return { default: (await import("./config-guide-presentation-BQdHuc5R.js")).ConfigGuidePresentationLayer };
173728
174086
  });
173729
174087
  /** Access the root-owned adaptive Guide runtime. */
173730
174088
  function useConfigGuide() {
@@ -178754,6 +179112,8 @@ async function refreshDashboardGitSnapshot(reason, expectedBindingToken) {
178754
179112
  *
178755
179113
  * Original request (2026-07-16): "接下来,你来接手后续工作"
178756
179114
  * Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
179115
+ * Original request (2026-09-18): owner walkthrough Case 5 — the compact Kanban cards kept the
179116
+ * generic scaffold heading "Proposal"; normalize active/archive card names once at the route.
178757
179117
  * Derived requirement (2026-07-19): Checkpoint 6.11 preserves Git handoff and action provenance.
178758
179118
  * Original request (2026-07-23): "现在页面数据的加载数据非常慢(比如dashboard页面、changes页面都要等待非常久,页面刷新后,似乎后台没有缓存一样,也要加载很久。"
178759
179119
  * Original request (2026-07-27): "统一修复所有类似的问题(我们也没不多,各个页面都检查一下,特别是app 那边新增的页面)"
@@ -178766,6 +179126,8 @@ async function refreshDashboardGitSnapshot(reason, expectedBindingToken) {
178766
179126
  * Original request (2026-07-31): "基于真实的布局去做骨架屏,或者说是直接让卡片自身去支持 Pending 样式"
178767
179127
  * Original request (2026-07-31): "Code Git Snapshot 的 Other Worktrees 默认隐藏 (detached)。然后commitList这里默认显示5个就好"
178768
179128
  * Original request (2026-07-31): "检查目前的这个 Code Git Snapshot,它非常慢,有时候甚至要十几秒"
179129
+ * Original request (2026-09-12): Owner walkthrough: unify the Change display title — generic
179130
+ * "# Proposal" headings fall back to the change id on every surface.
178769
179131
  * Owner correction (2026-07-31): Hidden documents pause the timer; visibility resumes the remaining delay or refreshes once when the absolute deadline elapsed.
178770
179132
 
178771
179133
  */
@@ -179006,7 +179368,14 @@ function Dashboard() {
179006
179368
  gitAutoRefreshPreset,
179007
179369
  staticMode
179008
179370
  ]);
179009
- const activeChanges = summaryProjection?.activeChanges ?? [];
179371
+ const activeChanges = (0, import_react.useMemo)(() => (summaryProjection?.activeChanges ?? []).map((change) => ({
179372
+ ...change,
179373
+ name: changeDisplayTitle(change.id, change.name)
179374
+ })), [summaryProjection?.activeChanges]);
179375
+ const kanbanArchivedItems = (0, import_react.useMemo)(() => (summaryProjection?.recentArchives ?? []).map((archive) => ({
179376
+ ...archive,
179377
+ name: changeDisplayTitle(archive.id, archive.name)
179378
+ })), [summaryProjection?.recentArchives]);
179010
179379
  const activeChangeIdSet = (0, import_react.useMemo)(() => new Set(activeChanges.map((change) => change.id)), [activeChanges]);
179011
179380
  const activeStatuses = (0, import_react.useMemo)(() => {
179012
179381
  return (statuses ?? []).filter((status) => activeChangeIdSet.has(status.changeName));
@@ -179105,7 +179474,7 @@ function Dashboard() {
179105
179474
  variant: "compact",
179106
179475
  pending: summaryPending,
179107
179476
  activeItems: activeChanges,
179108
- archivedItems: summaryProjection?.recentArchives ?? [],
179477
+ archivedItems: kanbanArchivedItems,
179109
179478
  activeCounts: summaryProjection?.trackedTaskPhaseCounts ?? {
179110
179479
  "no-tasks": 0,
179111
179480
  "in-progress": 0,
@@ -179254,7 +179623,7 @@ function Dashboard() {
179254
179623
  __vtHandoff: {
179255
179624
  family: "changes",
179256
179625
  entityId: change.id,
179257
- title: change.name,
179626
+ title: changeDisplayTitle(change.id, change.name),
179258
179627
  subtitle: change.id
179259
179628
  }
179260
179629
  }),
@@ -179271,7 +179640,7 @@ function Dashboard() {
179271
179640
  className: "flex min-w-0 items-center gap-3",
179272
179641
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChangeRow, {
179273
179642
  changeId: change.id,
179274
- name: change.name,
179643
+ name: changeDisplayTitle(change.id, change.name),
179275
179644
  phase,
179276
179645
  updatedAt: change.updatedAt,
179277
179646
  formatTime: formatRelativeTime,