@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.
- package/dist/assets/{App-Dmag08k5.js → App-C6nQouC6.js} +153 -153
- package/dist/assets/{App-BagQkLCd.css → App-CYwWbLgm.css} +1 -1
- package/dist/assets/{main-DXjJbv3-.js → main-CGJ5sQ3N.js} +2 -2
- package/dist/assets/{trpc-CENMN-Kx.js → trpc-Cq_wSpa5.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-ssg/client/.vite/ssr-manifest.json +59 -29
- package/dist-ssg/client/assets/CanvasRenderer-Dxe-hfnN.js +1 -0
- package/dist-ssg/client/assets/WebGLRenderer-CUJXjtiP.js +1 -0
- package/dist-ssg/client/assets/WebGPURenderer-CZL-JNBq.js +1 -0
- package/dist-ssg/client/assets/browserAll-5wBADmKd.js +1 -0
- package/dist-ssg/client/assets/{config-guide-presentation-GtsojPuN.js → config-guide-presentation-DqNeQzUr.js} +1 -1
- package/dist-ssg/client/assets/dist-9A8186dQ.js +1 -0
- package/dist-ssg/client/assets/{dist-BxTQbErr.js → dist-BD3jMQZ6.js} +1 -1
- package/dist-ssg/client/assets/dist-BMEQqWwb.js +1 -0
- package/dist-ssg/client/assets/dist-BTKdGHSA.js +1 -0
- package/dist-ssg/client/assets/{dist-C7lTRiju.js → dist-Bbhzl31A.js} +1 -1
- package/dist-ssg/client/assets/{dist-BAP9yhhm.js → dist-CY1qnMaG.js} +1 -1
- package/dist-ssg/client/assets/{dist-CI3zBObR.js → dist-CaeREplI.js} +1 -1
- package/dist-ssg/client/assets/{dist-Df3fSUJ8.js → dist-CdubN8-m.js} +1 -1
- package/dist-ssg/client/assets/{dist-B0xIEOgo.js → dist-DImGv92l.js} +1 -1
- package/dist-ssg/client/assets/{dist-DHkPjBBo.js → dist-DvFFLa-_.js} +1 -1
- package/dist-ssg/client/assets/{dist-CJOMMo-D.js → dist-DvI6Bh6U.js} +1 -1
- package/dist-ssg/client/assets/{dist-Cgf7W726.js → dist-FrX9lO7v.js} +1 -1
- package/dist-ssg/client/assets/{ghostty-web-VZE4TZBO.js → ghostty-web-iJUDy0Q_.js} +1 -1
- package/dist-ssg/client/assets/{index-CS0xsSqt.css → index-CMfi0IZJ.css} +1 -1
- package/dist-ssg/client/assets/{index.ssg-m0qZ-Tbv.js → index.ssg-C1gQDtR3.js} +134 -134
- package/dist-ssg/client/assets/{init-0qJSx79q.js → init-CXOzxy8a.js} +1 -1
- package/dist-ssg/client/assets/{trpc-D4bSp4J9.js → trpc-DeGTgf0N.js} +1 -1
- package/dist-ssg/client/assets/webworkerAll-D2PWaP7M.js +1 -0
- package/dist-ssg/client/index.ssg.html +2 -2
- package/dist-ssg/server/assets/CanvasRenderer-B1MUQY2W.js +3 -0
- package/dist-ssg/server/assets/WebGLRenderer-DIOoeqKv.js +3 -0
- package/dist-ssg/server/assets/WebGPURenderer-hzdCHpRg.js +3 -0
- package/dist-ssg/server/assets/{browserAll-Da2y8ybl.js → browserAll-C3aU2kkg.js} +2 -2
- package/dist-ssg/server/assets/{config-guide-presentation-GWnVFKTW.js → config-guide-presentation-BQdHuc5R.js} +1 -1
- package/dist-ssg/server/assets/{dist-DHhdkqG1.js → dist-BrgApT3v.js} +1 -1
- package/dist-ssg/server/assets/{dist-QLG95fVW.js → dist-BuA1hNQD.js} +1 -1
- package/dist-ssg/server/assets/{dist-CmE7gK9r.js → dist-C8tud7al.js} +1 -1
- package/dist-ssg/server/assets/{dist-dHhPmrtl.js → dist-CYFz-Xe6.js} +1 -1
- package/dist-ssg/server/assets/{dist-C8mczL_o.js → dist-CeAwBeY0.js} +1 -1
- package/dist-ssg/server/assets/dist-DQfK_0MA.js +3 -0
- package/dist-ssg/server/assets/{dist-Bk9be2-W.js → dist-DVq3OitZ.js} +1 -1
- package/dist-ssg/server/assets/dist-DhIAeIAf.js +3 -0
- package/dist-ssg/server/assets/{dist-CRw-jyve.js → dist-DoPtyXvU.js} +1 -1
- package/dist-ssg/server/assets/{dist-A6g9ScYS.js → dist-cd39lbM_.js} +1 -1
- package/dist-ssg/server/assets/{dist-D3Ubfaie.js → dist-uLS_wgVI.js} +1 -1
- package/dist-ssg/server/assets/dist-wVpQUanK.js +3 -0
- package/dist-ssg/server/assets/{entry-server-B1byBTHL.js → entry-server-DOzQvxeU.js} +459 -90
- package/dist-ssg/server/assets/{init-BCpyot27.js → init-Dw3wIW5D.js} +1 -1
- package/dist-ssg/server/assets/trpc-CE2cP14O.js +3 -0
- package/dist-ssg/server/assets/webworkerAll-CMJ1pR5p.js +4 -0
- package/dist-ssg/server/ssr-entry-manifest.json +24 -24
- package/package.json +3 -3
- package/dist-ssg/client/assets/CanvasRenderer-B3YNEZKU.js +0 -1
- package/dist-ssg/client/assets/WebGLRenderer-91FdO4XE.js +0 -1
- package/dist-ssg/client/assets/WebGPURenderer-BcSREi3g.js +0 -1
- package/dist-ssg/client/assets/browserAll-CRvGxmXW.js +0 -1
- package/dist-ssg/client/assets/dist-Bsojfco7.js +0 -1
- package/dist-ssg/client/assets/dist-fJz8f69P.js +0 -1
- package/dist-ssg/client/assets/dist-we8a11kz.js +0 -1
- package/dist-ssg/client/assets/webworkerAll-BUpVAcIt.js +0 -1
- package/dist-ssg/server/assets/CanvasRenderer-eDcOd6Sl.js +0 -3
- package/dist-ssg/server/assets/WebGLRenderer-BYGgdFoJ.js +0 -3
- package/dist-ssg/server/assets/WebGPURenderer-CS5mt9ch.js +0 -3
- package/dist-ssg/server/assets/dist-C8ZGbZgL.js +0 -3
- package/dist-ssg/server/assets/dist-D2ilXjzO.js +0 -3
- package/dist-ssg/server/assets/dist-DbHDr3r9.js +0 -3
- package/dist-ssg/server/assets/trpc-D5UIUAYV.js +0 -3
- 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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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-
|
|
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
|
|
171421
|
-
*
|
|
171422
|
-
*
|
|
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
|
-
|
|
171427
|
-
|
|
171428
|
-
|
|
171429
|
-
|
|
171430
|
-
|
|
171431
|
-
|
|
171432
|
-
|
|
171433
|
-
|
|
171434
|
-
|
|
171435
|
-
|
|
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)(
|
|
171438
|
-
className: "
|
|
171439
|
-
|
|
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.
|
|
171442
|
-
|
|
171443
|
-
|
|
171444
|
-
|
|
171445
|
-
|
|
171446
|
-
|
|
171447
|
-
|
|
171448
|
-
|
|
171449
|
-
|
|
171450
|
-
|
|
171451
|
-
|
|
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.
|
|
171602
|
-
var OPENSPEC_CLI_SUPPORTED_SERIES = ["1.
|
|
171603
|
-
var OPENSPEC_CLI_ACCEPTED_RANGE = ">=1.
|
|
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.
|
|
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.
|
|
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.
|
|
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-
|
|
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.
|
|
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-
|
|
172570
|
-
* 1. Present the OpenSpec 1.12 `validate --report findings` document
|
|
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-
|
|
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:
|
|
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, {
|
|
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-
|
|
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:
|
|
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,
|