openspecui 1.1.0 → 1.1.2

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 (31) hide show
  1. package/dist/cli.mjs +2 -2
  2. package/dist/index.mjs +1 -1
  3. package/dist/{src-Blkm4bri.mjs → src-C7k9J6Bv.mjs} +406 -496
  4. package/package.json +3 -3
  5. package/web/assets/{BufferResource-KG-p0IOw.js → BufferResource-ruI1lJIJ.js} +1 -1
  6. package/web/assets/{CanvasRenderer-BPfl0c8d.js → CanvasRenderer-CN4Y26ZH.js} +1 -1
  7. package/web/assets/{Filter-sQUNKII9.js → Filter-BTjr3eok.js} +1 -1
  8. package/web/assets/{RenderTargetSystem-CSquML7C.js → RenderTargetSystem-CZa2ln2y.js} +1 -1
  9. package/web/assets/{WebGLRenderer-CPYSMilB.js → WebGLRenderer-BJQTLaSb.js} +1 -1
  10. package/web/assets/{WebGPURenderer-Bovmcf9p.js → WebGPURenderer-BcNgCRe5.js} +1 -1
  11. package/web/assets/{browserAll-_92r-5ac.js → browserAll-ChJbTPze.js} +1 -1
  12. package/web/assets/{index-CoXK9782.js → index--L_QdP-6.js} +380 -267
  13. package/web/assets/{index-ENMQhAMb.js → index-7wPrcnqL.js} +1 -1
  14. package/web/assets/{index-GtwqqNfM.js → index-BX2oqbsU.js} +1 -1
  15. package/web/assets/{index-b1FuLUbQ.js → index-BbhkBFut.js} +1 -1
  16. package/web/assets/index-BfjQi4qu.css +1 -0
  17. package/web/assets/{index-CkR7zKp1.js → index-C7mTgvb9.js} +1 -1
  18. package/web/assets/{index-B0a0mXCT.js → index-CNeO03Fc.js} +1 -1
  19. package/web/assets/{index-BFQ55BqG.js → index-Cenc0P-m.js} +1 -1
  20. package/web/assets/{index-LF6Be7q3.js → index-CwjzVtxK.js} +1 -1
  21. package/web/assets/{index-ByxmpFP2.js → index-DVpS5GHp.js} +1 -1
  22. package/web/assets/{index-y0oP6zTz.js → index-DrCDnKl4.js} +1 -1
  23. package/web/assets/{index-CplS2l3l.js → index-Dw9lVmn9.js} +1 -1
  24. package/web/assets/{index-Cg50zItY.js → index-DwoTlpGw.js} +1 -1
  25. package/web/assets/{index-BXivRAdl.js → index-Y62s8n_r.js} +1 -1
  26. package/web/assets/{index-CaAELUfb.js → index-ikUsdiVm.js} +1 -1
  27. package/web/assets/{index-Dk5J-kBe.js → index-w-3qupYf.js} +1 -1
  28. package/web/assets/{index-Duv3IogN.js → index-ySiN9oO6.js} +1 -1
  29. package/web/assets/{webworkerAll-D2YreFOf.js → webworkerAll-Bd8axVrm.js} +1 -1
  30. package/web/index.html +2 -2
  31. package/web/assets/index-Ctf2SG7R.css +0 -1
@@ -13657,7 +13657,7 @@ var require_public_api = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnp
13657
13657
  }
13658
13658
  return doc;
13659
13659
  }
13660
- function parse$4(src, reviver, options) {
13660
+ function parse$3(src, reviver, options) {
13661
13661
  let _reviver = void 0;
13662
13662
  if (typeof reviver === "function") _reviver = reviver;
13663
13663
  else if (options === void 0 && reviver && typeof reviver === "object") options = reviver;
@@ -13684,7 +13684,7 @@ var require_public_api = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnp
13684
13684
  if (identity$2.isDocument(value) && !_replacer) return value.toString(options);
13685
13685
  return new Document$1.Document(value, _replacer, options).toString(options);
13686
13686
  }
13687
- exports.parse = parse$4;
13687
+ exports.parse = parse$3;
13688
13688
  exports.parseAllDocuments = parseAllDocuments;
13689
13689
  exports.parseDocument = parseDocument;
13690
13690
  exports.stringify = stringify;
@@ -13741,8 +13741,8 @@ var require_dist = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm/yaml
13741
13741
 
13742
13742
  //#endregion
13743
13743
  //#region ../core/src/opsx-kernel.ts
13744
- var import_dist$1 = require_dist();
13745
- function parseCliJson$1(raw$1, schema$6, label) {
13744
+ var import_dist = require_dist();
13745
+ function parseCliJson(raw$1, schema$6, label) {
13746
13746
  const trimmed = raw$1.trim();
13747
13747
  if (!trimmed) throw new Error(`${label} returned empty output`);
13748
13748
  let parsed;
@@ -13756,10 +13756,10 @@ function parseCliJson$1(raw$1, schema$6, label) {
13756
13756
  if (!result.success) throw new Error(`${label} returned unexpected JSON: ${result.error.message}`);
13757
13757
  return result.data;
13758
13758
  }
13759
- function toRelativePath$1(root, absolutePath) {
13759
+ function toRelativePath(root, absolutePath) {
13760
13760
  return relative$1(root, absolutePath).split(sep).join("/");
13761
13761
  }
13762
- async function readEntriesUnderRoot$1(root) {
13762
+ async function readEntriesUnderRoot(root) {
13763
13763
  if (!(await reactiveStat(root))?.isDirectory) return [];
13764
13764
  const collectEntries = async (dir) => {
13765
13765
  const names = await reactiveReadDir(dir, { includeHidden: false });
@@ -13768,7 +13768,7 @@ async function readEntriesUnderRoot$1(root) {
13768
13768
  const fullPath = join$1(dir, name);
13769
13769
  const statInfo = await reactiveStat(fullPath);
13770
13770
  if (!statInfo) continue;
13771
- const relativePath = toRelativePath$1(root, fullPath);
13771
+ const relativePath = toRelativePath(root, fullPath);
13772
13772
  if (statInfo.isDirectory) {
13773
13773
  entries.push({
13774
13774
  path: relativePath,
@@ -13790,14 +13790,14 @@ async function readEntriesUnderRoot$1(root) {
13790
13790
  };
13791
13791
  return collectEntries(root);
13792
13792
  }
13793
- async function readGlobArtifactFiles$1(projectDir, changeId, outputPath) {
13794
- return (await readEntriesUnderRoot$1(join$1(projectDir, "openspec", "changes", changeId))).filter((entry) => entry.type === "file" && matchesGlob(entry.path, outputPath)).map((entry) => ({
13793
+ async function readGlobArtifactFiles(projectDir, changeId, outputPath) {
13794
+ return (await readEntriesUnderRoot(join$1(projectDir, "openspec", "changes", changeId))).filter((entry) => entry.type === "file" && matchesGlob(entry.path, outputPath)).map((entry) => ({
13795
13795
  path: entry.path,
13796
13796
  type: "file",
13797
13797
  content: entry.content ?? ""
13798
13798
  }));
13799
13799
  }
13800
- async function touchOpsxProjectDeps$1(projectDir) {
13800
+ async function touchOpsxProjectDeps(projectDir) {
13801
13801
  const openspecDir = join$1(projectDir, "openspec");
13802
13802
  await reactiveReadFile(join$1(openspecDir, "config.yaml"));
13803
13803
  const schemaRoot = join$1(openspecDir, "schemas");
@@ -13812,7 +13812,7 @@ async function touchOpsxProjectDeps$1(projectDir) {
13812
13812
  exclude: ["archive"]
13813
13813
  });
13814
13814
  }
13815
- async function touchOpsxChangeDeps$1(projectDir, changeId) {
13815
+ async function touchOpsxChangeDeps(projectDir, changeId) {
13816
13816
  const changeDir = join$1(projectDir, "openspec", "changes", changeId);
13817
13817
  await reactiveReadDir(changeDir, { includeHidden: true });
13818
13818
  await reactiveReadFile(join$1(changeDir, ".openspec.yaml"));
@@ -13821,6 +13821,8 @@ var OpsxKernel = class {
13821
13821
  projectDir;
13822
13822
  cliExecutor;
13823
13823
  controller = new AbortController();
13824
+ warmupPromise = null;
13825
+ _streamReady = /* @__PURE__ */ new Map();
13824
13826
  _statusList = new ReactiveState([]);
13825
13827
  _schemas = new ReactiveState([]);
13826
13828
  _changeIds = new ReactiveState([]);
@@ -13843,17 +13845,28 @@ var OpsxKernel = class {
13843
13845
  this.cliExecutor = cliExecutor;
13844
13846
  }
13845
13847
  async warmup() {
13848
+ if (this.warmupPromise) return this.warmupPromise;
13849
+ this.warmupPromise = this.runWarmup().catch((error) => {
13850
+ this.warmupPromise = null;
13851
+ throw error;
13852
+ });
13853
+ return this.warmupPromise;
13854
+ }
13855
+ async waitForWarmup() {
13856
+ await this.warmup();
13857
+ }
13858
+ async runWarmup() {
13846
13859
  const signal = this.controller.signal;
13847
13860
  await Promise.all([
13848
- this.startStream(this._schemas, () => this.fetchSchemas(), signal),
13849
- this.startStream(this._changeIds, () => this.fetchChangeIds(), signal),
13850
- this.startStream(this._projectConfig, () => this.fetchProjectConfig(), signal)
13861
+ this.startStreamOnce("global:schemas", this._schemas, () => this.fetchSchemas(), signal),
13862
+ this.startStreamOnce("global:change-ids", this._changeIds, () => this.fetchChangeIds(), signal),
13863
+ this.startStreamOnce("global:project-config", this._projectConfig, () => this.fetchProjectConfig(), signal)
13851
13864
  ]);
13852
13865
  const schemas$1 = this._schemas.get();
13853
13866
  await Promise.all(schemas$1.map((s) => this.warmupSchema(s.name, signal)));
13854
13867
  const changeIds = this._changeIds.get();
13855
13868
  await Promise.all(changeIds.map((id) => this.warmupChange(id, signal)));
13856
- await this.startStream(this._statusList, () => this.fetchStatusList(), signal);
13869
+ await this.startStreamOnce("global:status-list", this._statusList, () => this.fetchStatusList(), signal);
13857
13870
  this.watchSchemaChanges(signal);
13858
13871
  this.watchChangeIdChanges(signal);
13859
13872
  }
@@ -13861,6 +13874,8 @@ var OpsxKernel = class {
13861
13874
  this.controller.abort();
13862
13875
  for (const ctrl of this._entityControllers.values()) ctrl.abort();
13863
13876
  this._entityControllers.clear();
13877
+ this._streamReady.clear();
13878
+ this.warmupPromise = null;
13864
13879
  }
13865
13880
  getStatusList() {
13866
13881
  return this._statusList.get();
@@ -13907,11 +13922,21 @@ var OpsxKernel = class {
13907
13922
  if (!state) throw new Error(`Schema resolution not found for "${name}"`);
13908
13923
  return state.get();
13909
13924
  }
13925
+ peekSchemaResolution(name) {
13926
+ const state = this._schemaResolutions.get(name);
13927
+ if (!state) return null;
13928
+ return state.get() ?? null;
13929
+ }
13910
13930
  getSchemaDetail(name) {
13911
13931
  const state = this._schemaDetails.get(name);
13912
13932
  if (!state) throw new Error(`Schema detail not found for "${name}"`);
13913
13933
  return state.get();
13914
13934
  }
13935
+ peekSchemaDetail(name) {
13936
+ const state = this._schemaDetails.get(name);
13937
+ if (!state) return null;
13938
+ return state.get() ?? null;
13939
+ }
13915
13940
  getSchemaFiles(name) {
13916
13941
  const state = this._schemaFiles.get(name);
13917
13942
  if (!state) throw new Error(`Schema files not found for "${name}"`);
@@ -13940,7 +13965,7 @@ var OpsxKernel = class {
13940
13965
  return state.get();
13941
13966
  }
13942
13967
  startStream(state, task, signal) {
13943
- return new Promise((resolve$2) => {
13968
+ return new Promise((resolve$2, reject) => {
13944
13969
  const context = new ReactiveContext();
13945
13970
  let first = true;
13946
13971
  (async () => {
@@ -13952,12 +13977,28 @@ var OpsxKernel = class {
13952
13977
  resolve$2();
13953
13978
  }
13954
13979
  }
13955
- } catch {}
13980
+ } catch (error) {
13981
+ if (first && !signal.aborted) {
13982
+ reject(error);
13983
+ return;
13984
+ }
13985
+ }
13956
13986
  if (first) resolve$2();
13957
13987
  })();
13958
13988
  });
13959
13989
  }
13990
+ startStreamOnce(key, state, task, signal) {
13991
+ const existing = this._streamReady.get(key);
13992
+ if (existing) return existing;
13993
+ const ready = this.startStream(state, task, signal).catch((error) => {
13994
+ this._streamReady.delete(key);
13995
+ throw error;
13996
+ });
13997
+ this._streamReady.set(key, ready);
13998
+ return ready;
13999
+ }
13960
14000
  async warmupSchema(name, parentSignal) {
14001
+ if (this._entityControllers.has(`schema:${name}`)) return;
13961
14002
  const entityCtrl = new AbortController();
13962
14003
  this._entityControllers.set(`schema:${name}`, entityCtrl);
13963
14004
  const signal = this.combineSignals(parentSignal, entityCtrl.signal);
@@ -13970,17 +14011,18 @@ var OpsxKernel = class {
13970
14011
  if (!this._templates.has("")) this._templates.set("", new ReactiveState({}));
13971
14012
  if (!this._templateContents.has("")) this._templateContents.set("", new ReactiveState({}));
13972
14013
  await Promise.all([
13973
- this.startStream(this._schemaResolutions.get(name), () => this.fetchSchemaResolution(name), signal),
13974
- this.startStream(this._schemaDetails.get(name), () => this.fetchSchemaDetail(name), signal),
13975
- this.startStream(this._schemaFiles.get(name), () => this.fetchSchemaFiles(name), signal),
13976
- this.startStream(this._schemaYamls.get(name), () => this.fetchSchemaYaml(name), signal),
13977
- this.startStream(this._templates.get(name), () => this.fetchTemplates(name), signal),
13978
- this.startStream(this._templateContents.get(name), () => this.fetchTemplateContents(name), signal),
13979
- this.startStream(this._templates.get(""), () => this.fetchTemplates(void 0), signal),
13980
- this.startStream(this._templateContents.get(""), () => this.fetchTemplateContents(void 0), signal)
14014
+ this.startStreamOnce(`schema:${name}:resolution`, this._schemaResolutions.get(name), () => this.fetchSchemaResolution(name), signal),
14015
+ this.startStreamOnce(`schema:${name}:detail`, this._schemaDetails.get(name), () => this.fetchSchemaDetail(name), signal),
14016
+ this.startStreamOnce(`schema:${name}:files`, this._schemaFiles.get(name), () => this.fetchSchemaFiles(name), signal),
14017
+ this.startStreamOnce(`schema:${name}:yaml`, this._schemaYamls.get(name), () => this.fetchSchemaYaml(name), signal),
14018
+ this.startStreamOnce(`schema:${name}:templates`, this._templates.get(name), () => this.fetchTemplates(name), signal),
14019
+ this.startStreamOnce(`schema:${name}:template-contents`, this._templateContents.get(name), () => this.fetchTemplateContents(name), signal),
14020
+ this.startStreamOnce("schema::templates", this._templates.get(""), () => this.fetchTemplates(void 0), signal),
14021
+ this.startStreamOnce("schema::template-contents", this._templateContents.get(""), () => this.fetchTemplateContents(void 0), signal)
13981
14022
  ]);
13982
14023
  }
13983
14024
  async warmupChange(changeId, parentSignal) {
14025
+ if (this._entityControllers.has(`change:${changeId}`)) return;
13984
14026
  const entityCtrl = new AbortController();
13985
14027
  this._entityControllers.set(`change:${changeId}`, entityCtrl);
13986
14028
  const signal = this.combineSignals(parentSignal, entityCtrl.signal);
@@ -13990,22 +14032,22 @@ var OpsxKernel = class {
13990
14032
  const applyKey = `${changeId}:`;
13991
14033
  if (!this._applyInstructions.has(applyKey)) this._applyInstructions.set(applyKey, new ReactiveState(null));
13992
14034
  await Promise.all([
13993
- this.startStream(this._statuses.get(statusKey), () => this.fetchStatus(changeId, void 0), signal),
13994
- this.startStream(this._changeMetadata.get(changeId), () => this.fetchChangeMetadata(changeId), signal),
13995
- this.startStream(this._applyInstructions.get(applyKey), () => this.fetchApplyInstructions(changeId, void 0), signal)
14035
+ this.startStreamOnce(`change:${changeId}:status:`, this._statuses.get(statusKey), () => this.fetchStatus(changeId, void 0), signal),
14036
+ this.startStreamOnce(`change:${changeId}:metadata`, this._changeMetadata.get(changeId), () => this.fetchChangeMetadata(changeId), signal),
14037
+ this.startStreamOnce(`change:${changeId}:apply:`, this._applyInstructions.get(applyKey), () => this.fetchApplyInstructions(changeId, void 0), signal)
13996
14038
  ]);
13997
14039
  const status = this._statuses.get(statusKey)?.get();
13998
14040
  if (status?.artifacts) await Promise.all(status.artifacts.map(async (artifact) => {
13999
14041
  const instrKey = `${changeId}:${artifact.id}:`;
14000
14042
  if (!this._instructions.has(instrKey)) this._instructions.set(instrKey, new ReactiveState(null));
14001
- await this.startStream(this._instructions.get(instrKey), () => this.fetchInstructions(changeId, artifact.id, void 0), signal);
14043
+ await this.startStreamOnce(`change:${changeId}:instructions:${artifact.id}:`, this._instructions.get(instrKey), () => this.fetchInstructions(changeId, artifact.id, void 0), signal);
14002
14044
  const outputKey = `${changeId}:${artifact.outputPath}`;
14003
14045
  if (!this._artifactOutputs.has(outputKey)) this._artifactOutputs.set(outputKey, new ReactiveState(null));
14004
- await this.startStream(this._artifactOutputs.get(outputKey), () => this.fetchArtifactOutput(changeId, artifact.outputPath), signal);
14046
+ await this.startStreamOnce(`change:${changeId}:output:${artifact.outputPath}`, this._artifactOutputs.get(outputKey), () => this.fetchArtifactOutput(changeId, artifact.outputPath), signal);
14005
14047
  if (artifact.outputPath.includes("*") || artifact.outputPath.includes("?") || artifact.outputPath.includes("[")) {
14006
14048
  const globKey = `${changeId}:${artifact.outputPath}`;
14007
14049
  if (!this._globArtifactFiles.has(globKey)) this._globArtifactFiles.set(globKey, new ReactiveState([]));
14008
- await this.startStream(this._globArtifactFiles.get(globKey), () => readGlobArtifactFiles$1(this.projectDir, changeId, artifact.outputPath), signal);
14050
+ await this.startStreamOnce(`change:${changeId}:glob:${artifact.outputPath}`, this._globArtifactFiles.get(globKey), () => readGlobArtifactFiles(this.projectDir, changeId, artifact.outputPath), signal);
14009
14051
  }
14010
14052
  }));
14011
14053
  }
@@ -14016,7 +14058,7 @@ var OpsxKernel = class {
14016
14058
  try {
14017
14059
  for await (const schemas$1 of context.stream(() => Promise.resolve(this._schemas.get()), signal)) {
14018
14060
  const newNames = new Set(schemas$1.map((s) => s.name));
14019
- for (const name of newNames) if (!prevNames.has(name)) this.warmupSchema(name, signal);
14061
+ for (const name of newNames) if (!prevNames.has(name)) this.warmupSchema(name, signal).catch(() => {});
14020
14062
  for (const name of prevNames) if (!newNames.has(name)) {
14021
14063
  this.teardownEntity(`schema:${name}`);
14022
14064
  this._schemaResolutions.delete(name);
@@ -14025,6 +14067,7 @@ var OpsxKernel = class {
14025
14067
  this._schemaYamls.delete(name);
14026
14068
  this._templates.delete(name);
14027
14069
  this._templateContents.delete(name);
14070
+ this.clearStreamReadyByPrefix(`schema:${name}:`);
14028
14071
  }
14029
14072
  prevNames = newNames;
14030
14073
  }
@@ -14038,15 +14081,33 @@ var OpsxKernel = class {
14038
14081
  try {
14039
14082
  for await (const ids of context.stream(() => Promise.resolve(this._changeIds.get()), signal)) {
14040
14083
  const newIds = new Set(ids);
14041
- for (const id of newIds) if (!prevIds.has(id)) this.warmupChange(id, signal);
14084
+ for (const id of newIds) if (!prevIds.has(id)) this.warmupChange(id, signal).catch(() => {});
14042
14085
  for (const id of prevIds) if (!newIds.has(id)) {
14043
14086
  this.teardownEntity(`change:${id}`);
14044
- for (const key of this._statuses.keys()) if (key.startsWith(`${id}:`)) this._statuses.delete(key);
14045
- for (const key of this._instructions.keys()) if (key.startsWith(`${id}:`)) this._instructions.delete(key);
14046
- for (const key of this._applyInstructions.keys()) if (key.startsWith(`${id}:`)) this._applyInstructions.delete(key);
14087
+ for (const key of this._statuses.keys()) if (key.startsWith(`${id}:`)) {
14088
+ this._statuses.delete(key);
14089
+ this._streamReady.delete(`change:${id}:status:${key.slice(id.length + 1)}`);
14090
+ }
14091
+ for (const key of this._instructions.keys()) if (key.startsWith(`${id}:`)) {
14092
+ this._instructions.delete(key);
14093
+ const suffix = key.slice(id.length + 1);
14094
+ this._streamReady.delete(`change:${id}:instructions:${suffix}`);
14095
+ }
14096
+ for (const key of this._applyInstructions.keys()) if (key.startsWith(`${id}:`)) {
14097
+ this._applyInstructions.delete(key);
14098
+ this._streamReady.delete(`change:${id}:apply:${key.slice(id.length + 1)}`);
14099
+ }
14047
14100
  this._changeMetadata.delete(id);
14048
- for (const key of this._artifactOutputs.keys()) if (key.startsWith(`${id}:`)) this._artifactOutputs.delete(key);
14049
- for (const key of this._globArtifactFiles.keys()) if (key.startsWith(`${id}:`)) this._globArtifactFiles.delete(key);
14101
+ this._streamReady.delete(`change:${id}:metadata`);
14102
+ for (const key of this._artifactOutputs.keys()) if (key.startsWith(`${id}:`)) {
14103
+ this._artifactOutputs.delete(key);
14104
+ this._streamReady.delete(`change:${id}:output:${key.slice(id.length + 1)}`);
14105
+ }
14106
+ for (const key of this._globArtifactFiles.keys()) if (key.startsWith(`${id}:`)) {
14107
+ this._globArtifactFiles.delete(key);
14108
+ this._streamReady.delete(`change:${id}:glob:${key.slice(id.length + 1)}`);
14109
+ }
14110
+ this.clearStreamReadyByPrefix(`change:${id}:`);
14050
14111
  }
14051
14112
  prevIds = newIds;
14052
14113
  }
@@ -14060,11 +14121,14 @@ var OpsxKernel = class {
14060
14121
  this._entityControllers.delete(key);
14061
14122
  }
14062
14123
  }
14124
+ clearStreamReadyByPrefix(prefix) {
14125
+ for (const key of this._streamReady.keys()) if (key.startsWith(prefix)) this._streamReady.delete(key);
14126
+ }
14063
14127
  async fetchSchemas() {
14064
- await touchOpsxProjectDeps$1(this.projectDir);
14128
+ await touchOpsxProjectDeps(this.projectDir);
14065
14129
  const result = await this.cliExecutor.schemas();
14066
14130
  if (!result.success) throw new Error(result.stderr || `openspec schemas failed (exit ${result.exitCode ?? "null"})`);
14067
- return parseCliJson$1(result.stdout, arrayType(SchemaInfoSchema), "openspec schemas");
14131
+ return parseCliJson(result.stdout, arrayType(SchemaInfoSchema), "openspec schemas");
14068
14132
  }
14069
14133
  async fetchChangeIds() {
14070
14134
  return reactiveReadDir(join$1(this.projectDir, "openspec", "changes"), {
@@ -14077,8 +14141,8 @@ var OpsxKernel = class {
14077
14141
  return reactiveReadFile(join$1(this.projectDir, "openspec", "config.yaml"));
14078
14142
  }
14079
14143
  async fetchStatus(changeId, schema$6) {
14080
- await touchOpsxProjectDeps$1(this.projectDir);
14081
- await touchOpsxChangeDeps$1(this.projectDir, changeId);
14144
+ await touchOpsxProjectDeps(this.projectDir);
14145
+ await touchOpsxChangeDeps(this.projectDir, changeId);
14082
14146
  const args = [
14083
14147
  "status",
14084
14148
  "--json",
@@ -14088,23 +14152,20 @@ var OpsxKernel = class {
14088
14152
  if (schema$6) args.push("--schema", schema$6);
14089
14153
  const result = await this.cliExecutor.execute(args);
14090
14154
  if (!result.success) throw new Error(result.stderr || `openspec status failed (exit ${result.exitCode ?? "null"})`);
14091
- const status = parseCliJson$1(result.stdout, ChangeStatusSchema, "openspec status");
14155
+ const status = parseCliJson(result.stdout, ChangeStatusSchema, "openspec status");
14092
14156
  const changeRelDir = `openspec/changes/${changeId}`;
14093
14157
  for (const artifact of status.artifacts) artifact.relativePath = `${changeRelDir}/${artifact.outputPath}`;
14094
14158
  return status;
14095
14159
  }
14096
14160
  async fetchStatusList() {
14161
+ await this.ensureChangeIds();
14097
14162
  const changeIds = this._changeIds.get();
14098
- return Promise.all(changeIds.map((id) => {
14099
- const key = `${id}:`;
14100
- const state = this._statuses.get(key);
14101
- if (state) return Promise.resolve(state.get());
14102
- return this.fetchStatus(id);
14103
- }));
14163
+ await Promise.all(changeIds.map((id) => this.ensureStatus(id)));
14164
+ return changeIds.map((id) => this.getStatus(id));
14104
14165
  }
14105
14166
  async fetchInstructions(changeId, artifact, schema$6) {
14106
- await touchOpsxProjectDeps$1(this.projectDir);
14107
- await touchOpsxChangeDeps$1(this.projectDir, changeId);
14167
+ await touchOpsxProjectDeps(this.projectDir);
14168
+ await touchOpsxChangeDeps(this.projectDir, changeId);
14108
14169
  const args = [
14109
14170
  "instructions",
14110
14171
  artifact,
@@ -14115,11 +14176,11 @@ var OpsxKernel = class {
14115
14176
  if (schema$6) args.push("--schema", schema$6);
14116
14177
  const result = await this.cliExecutor.execute(args);
14117
14178
  if (!result.success) throw new Error(result.stderr || `openspec instructions failed (exit ${result.exitCode ?? "null"})`);
14118
- return parseCliJson$1(result.stdout, ArtifactInstructionsSchema, "openspec instructions");
14179
+ return parseCliJson(result.stdout, ArtifactInstructionsSchema, "openspec instructions");
14119
14180
  }
14120
14181
  async fetchApplyInstructions(changeId, schema$6) {
14121
- await touchOpsxProjectDeps$1(this.projectDir);
14122
- await touchOpsxChangeDeps$1(this.projectDir, changeId);
14182
+ await touchOpsxProjectDeps(this.projectDir);
14183
+ await touchOpsxChangeDeps(this.projectDir, changeId);
14123
14184
  const args = [
14124
14185
  "instructions",
14125
14186
  "apply",
@@ -14130,37 +14191,41 @@ var OpsxKernel = class {
14130
14191
  if (schema$6) args.push("--schema", schema$6);
14131
14192
  const result = await this.cliExecutor.execute(args);
14132
14193
  if (!result.success) throw new Error(result.stderr || `openspec instructions apply failed (exit ${result.exitCode ?? "null"})`);
14133
- return parseCliJson$1(result.stdout, ApplyInstructionsSchema, "openspec instructions apply");
14194
+ return parseCliJson(result.stdout, ApplyInstructionsSchema, "openspec instructions apply");
14134
14195
  }
14135
14196
  async fetchSchemaResolution(name) {
14136
- await touchOpsxProjectDeps$1(this.projectDir);
14197
+ await touchOpsxProjectDeps(this.projectDir);
14137
14198
  const result = await this.cliExecutor.schemaWhich(name);
14138
14199
  if (!result.success) throw new Error(result.stderr || `openspec schema which failed (exit ${result.exitCode ?? "null"})`);
14139
- return parseCliJson$1(result.stdout, SchemaResolutionSchema, "openspec schema which");
14200
+ return parseCliJson(result.stdout, SchemaResolutionSchema, "openspec schema which");
14140
14201
  }
14141
14202
  async fetchSchemaDetail(name) {
14142
- await touchOpsxProjectDeps$1(this.projectDir);
14143
- const schemaPath = join$1((await this.fetchSchemaResolution(name)).path, "schema.yaml");
14203
+ await touchOpsxProjectDeps(this.projectDir);
14204
+ await this.ensureSchemaResolution(name);
14205
+ const schemaPath = join$1(this.getSchemaResolution(name).path, "schema.yaml");
14144
14206
  const content = await reactiveReadFile(schemaPath);
14145
14207
  if (!content) throw new Error(`schema.yaml not found at ${schemaPath}`);
14146
14208
  return parseSchemaYamlInline(content);
14147
14209
  }
14148
14210
  async fetchSchemaFiles(name) {
14149
- await touchOpsxProjectDeps$1(this.projectDir);
14150
- return readEntriesUnderRoot$1((await this.fetchSchemaResolution(name)).path);
14211
+ await touchOpsxProjectDeps(this.projectDir);
14212
+ await this.ensureSchemaResolution(name);
14213
+ return readEntriesUnderRoot(this.getSchemaResolution(name).path);
14151
14214
  }
14152
14215
  async fetchSchemaYaml(name) {
14153
- await touchOpsxProjectDeps$1(this.projectDir);
14154
- return reactiveReadFile(join$1((await this.fetchSchemaResolution(name)).path, "schema.yaml"));
14216
+ await touchOpsxProjectDeps(this.projectDir);
14217
+ await this.ensureSchemaResolution(name);
14218
+ return reactiveReadFile(join$1(this.getSchemaResolution(name).path, "schema.yaml"));
14155
14219
  }
14156
14220
  async fetchTemplates(schema$6) {
14157
- await touchOpsxProjectDeps$1(this.projectDir);
14221
+ await touchOpsxProjectDeps(this.projectDir);
14158
14222
  const result = await this.cliExecutor.templates(schema$6);
14159
14223
  if (!result.success) throw new Error(result.stderr || `openspec templates failed (exit ${result.exitCode ?? "null"})`);
14160
- return parseCliJson$1(result.stdout, TemplatesSchema, "openspec templates");
14224
+ return parseCliJson(result.stdout, TemplatesSchema, "openspec templates");
14161
14225
  }
14162
14226
  async fetchTemplateContents(schema$6) {
14163
- const templates = await this.fetchTemplates(schema$6);
14227
+ await this.ensureTemplates(schema$6);
14228
+ const templates = this.getTemplates(schema$6);
14164
14229
  const entries = await Promise.all(Object.entries(templates).map(async ([artifactId, info]) => {
14165
14230
  return [artifactId, {
14166
14231
  content: await reactiveReadFile(info.path),
@@ -14176,88 +14241,72 @@ var OpsxKernel = class {
14176
14241
  async fetchArtifactOutput(changeId, outputPath) {
14177
14242
  return reactiveReadFile(join$1(this.projectDir, "openspec", "changes", changeId, outputPath));
14178
14243
  }
14179
- /**
14180
- * Ensure a per-change status stream exists. If not yet warmed up,
14181
- * creates the state and starts a stream lazily.
14182
- */
14183
- ensureStatus(changeId, schema$6) {
14244
+ async ensureSchemas() {
14245
+ await this.startStreamOnce("global:schemas", this._schemas, () => this.fetchSchemas(), this.controller.signal);
14246
+ }
14247
+ async ensureChangeIds() {
14248
+ await this.startStreamOnce("global:change-ids", this._changeIds, () => this.fetchChangeIds(), this.controller.signal);
14249
+ }
14250
+ async ensureProjectConfig() {
14251
+ await this.startStreamOnce("global:project-config", this._projectConfig, () => this.fetchProjectConfig(), this.controller.signal);
14252
+ }
14253
+ async ensureStatusList() {
14254
+ await this.startStreamOnce("global:status-list", this._statusList, () => this.fetchStatusList(), this.controller.signal);
14255
+ }
14256
+ async ensureStatus(changeId, schema$6) {
14184
14257
  const key = `${changeId}:${schema$6 ?? ""}`;
14185
- if (!this._statuses.has(key)) {
14186
- this._statuses.set(key, new ReactiveState(null));
14187
- this.startStream(this._statuses.get(key), () => this.fetchStatus(changeId, schema$6), this.controller.signal);
14188
- }
14258
+ if (!this._statuses.has(key)) this._statuses.set(key, new ReactiveState(null));
14259
+ await this.startStreamOnce(`change:${changeId}:status:${schema$6 ?? ""}`, this._statuses.get(key), () => this.fetchStatus(changeId, schema$6), this.controller.signal);
14189
14260
  }
14190
- ensureInstructions(changeId, artifact, schema$6) {
14261
+ async ensureInstructions(changeId, artifact, schema$6) {
14191
14262
  const key = `${changeId}:${artifact}:${schema$6 ?? ""}`;
14192
- if (!this._instructions.has(key)) {
14193
- this._instructions.set(key, new ReactiveState(null));
14194
- this.startStream(this._instructions.get(key), () => this.fetchInstructions(changeId, artifact, schema$6), this.controller.signal);
14195
- }
14263
+ if (!this._instructions.has(key)) this._instructions.set(key, new ReactiveState(null));
14264
+ await this.startStreamOnce(`change:${changeId}:instructions:${artifact}:${schema$6 ?? ""}`, this._instructions.get(key), () => this.fetchInstructions(changeId, artifact, schema$6), this.controller.signal);
14196
14265
  }
14197
- ensureApplyInstructions(changeId, schema$6) {
14266
+ async ensureApplyInstructions(changeId, schema$6) {
14198
14267
  const key = `${changeId}:${schema$6 ?? ""}`;
14199
- if (!this._applyInstructions.has(key)) {
14200
- this._applyInstructions.set(key, new ReactiveState(null));
14201
- this.startStream(this._applyInstructions.get(key), () => this.fetchApplyInstructions(changeId, schema$6), this.controller.signal);
14202
- }
14268
+ if (!this._applyInstructions.has(key)) this._applyInstructions.set(key, new ReactiveState(null));
14269
+ await this.startStreamOnce(`change:${changeId}:apply:${schema$6 ?? ""}`, this._applyInstructions.get(key), () => this.fetchApplyInstructions(changeId, schema$6), this.controller.signal);
14203
14270
  }
14204
- ensureArtifactOutput(changeId, outputPath) {
14271
+ async ensureArtifactOutput(changeId, outputPath) {
14205
14272
  const key = `${changeId}:${outputPath}`;
14206
- if (!this._artifactOutputs.has(key)) {
14207
- this._artifactOutputs.set(key, new ReactiveState(null));
14208
- this.startStream(this._artifactOutputs.get(key), () => this.fetchArtifactOutput(changeId, outputPath), this.controller.signal);
14209
- }
14273
+ if (!this._artifactOutputs.has(key)) this._artifactOutputs.set(key, new ReactiveState(null));
14274
+ await this.startStreamOnce(`change:${changeId}:output:${outputPath}`, this._artifactOutputs.get(key), () => this.fetchArtifactOutput(changeId, outputPath), this.controller.signal);
14210
14275
  }
14211
- ensureGlobArtifactFiles(changeId, outputPath) {
14276
+ async ensureGlobArtifactFiles(changeId, outputPath) {
14212
14277
  const key = `${changeId}:${outputPath}`;
14213
- if (!this._globArtifactFiles.has(key)) {
14214
- this._globArtifactFiles.set(key, new ReactiveState([]));
14215
- this.startStream(this._globArtifactFiles.get(key), () => readGlobArtifactFiles$1(this.projectDir, changeId, outputPath), this.controller.signal);
14216
- }
14278
+ if (!this._globArtifactFiles.has(key)) this._globArtifactFiles.set(key, new ReactiveState([]));
14279
+ await this.startStreamOnce(`change:${changeId}:glob:${outputPath}`, this._globArtifactFiles.get(key), () => readGlobArtifactFiles(this.projectDir, changeId, outputPath), this.controller.signal);
14217
14280
  }
14218
- ensureSchemaResolution(name) {
14219
- if (!this._schemaResolutions.has(name)) {
14220
- this._schemaResolutions.set(name, new ReactiveState(null));
14221
- this.startStream(this._schemaResolutions.get(name), () => this.fetchSchemaResolution(name), this.controller.signal);
14222
- }
14281
+ async ensureSchemaResolution(name) {
14282
+ if (!this._schemaResolutions.has(name)) this._schemaResolutions.set(name, new ReactiveState(null));
14283
+ await this.startStreamOnce(`schema:${name}:resolution`, this._schemaResolutions.get(name), () => this.fetchSchemaResolution(name), this.controller.signal);
14223
14284
  }
14224
- ensureSchemaDetail(name) {
14225
- if (!this._schemaDetails.has(name)) {
14226
- this._schemaDetails.set(name, new ReactiveState(null));
14227
- this.startStream(this._schemaDetails.get(name), () => this.fetchSchemaDetail(name), this.controller.signal);
14228
- }
14285
+ async ensureSchemaDetail(name) {
14286
+ if (!this._schemaDetails.has(name)) this._schemaDetails.set(name, new ReactiveState(null));
14287
+ await this.startStreamOnce(`schema:${name}:detail`, this._schemaDetails.get(name), () => this.fetchSchemaDetail(name), this.controller.signal);
14229
14288
  }
14230
- ensureSchemaFiles(name) {
14231
- if (!this._schemaFiles.has(name)) {
14232
- this._schemaFiles.set(name, new ReactiveState([]));
14233
- this.startStream(this._schemaFiles.get(name), () => this.fetchSchemaFiles(name), this.controller.signal);
14234
- }
14289
+ async ensureSchemaFiles(name) {
14290
+ if (!this._schemaFiles.has(name)) this._schemaFiles.set(name, new ReactiveState([]));
14291
+ await this.startStreamOnce(`schema:${name}:files`, this._schemaFiles.get(name), () => this.fetchSchemaFiles(name), this.controller.signal);
14235
14292
  }
14236
- ensureSchemaYaml(name) {
14237
- if (!this._schemaYamls.has(name)) {
14238
- this._schemaYamls.set(name, new ReactiveState(null));
14239
- this.startStream(this._schemaYamls.get(name), () => this.fetchSchemaYaml(name), this.controller.signal);
14240
- }
14293
+ async ensureSchemaYaml(name) {
14294
+ if (!this._schemaYamls.has(name)) this._schemaYamls.set(name, new ReactiveState(null));
14295
+ await this.startStreamOnce(`schema:${name}:yaml`, this._schemaYamls.get(name), () => this.fetchSchemaYaml(name), this.controller.signal);
14241
14296
  }
14242
- ensureTemplates(schema$6) {
14297
+ async ensureTemplates(schema$6) {
14243
14298
  const key = schema$6 ?? "";
14244
- if (!this._templates.has(key)) {
14245
- this._templates.set(key, new ReactiveState({}));
14246
- this.startStream(this._templates.get(key), () => this.fetchTemplates(schema$6), this.controller.signal);
14247
- }
14299
+ if (!this._templates.has(key)) this._templates.set(key, new ReactiveState({}));
14300
+ await this.startStreamOnce(`schema:${key}:templates`, this._templates.get(key), () => this.fetchTemplates(schema$6), this.controller.signal);
14248
14301
  }
14249
- ensureTemplateContents(schema$6) {
14302
+ async ensureTemplateContents(schema$6) {
14250
14303
  const key = schema$6 ?? "";
14251
- if (!this._templateContents.has(key)) {
14252
- this._templateContents.set(key, new ReactiveState({}));
14253
- this.startStream(this._templateContents.get(key), () => this.fetchTemplateContents(schema$6), this.controller.signal);
14254
- }
14304
+ if (!this._templateContents.has(key)) this._templateContents.set(key, new ReactiveState({}));
14305
+ await this.startStreamOnce(`schema:${key}:template-contents`, this._templateContents.get(key), () => this.fetchTemplateContents(schema$6), this.controller.signal);
14255
14306
  }
14256
- ensureChangeMetadata(changeId) {
14257
- if (!this._changeMetadata.has(changeId)) {
14258
- this._changeMetadata.set(changeId, new ReactiveState(null));
14259
- this.startStream(this._changeMetadata.get(changeId), () => this.fetchChangeMetadata(changeId), this.controller.signal);
14260
- }
14307
+ async ensureChangeMetadata(changeId) {
14308
+ if (!this._changeMetadata.has(changeId)) this._changeMetadata.set(changeId, new ReactiveState(null));
14309
+ await this.startStreamOnce(`change:${changeId}:metadata`, this._changeMetadata.get(changeId), () => this.fetchChangeMetadata(changeId), this.controller.signal);
14261
14310
  }
14262
14311
  combineSignals(a, b) {
14263
14312
  const ctrl = new AbortController();
@@ -14271,7 +14320,7 @@ var OpsxKernel = class {
14271
14320
  return ctrl.signal;
14272
14321
  }
14273
14322
  };
14274
- const SchemaYamlArtifactSchema$1 = objectType({
14323
+ const SchemaYamlArtifactSchema = objectType({
14275
14324
  id: stringType(),
14276
14325
  generates: stringType(),
14277
14326
  description: stringType().optional(),
@@ -14279,11 +14328,11 @@ const SchemaYamlArtifactSchema$1 = objectType({
14279
14328
  instruction: stringType().optional(),
14280
14329
  requires: arrayType(stringType()).optional()
14281
14330
  });
14282
- const SchemaYamlSchema$1 = objectType({
14331
+ const SchemaYamlSchema = objectType({
14283
14332
  name: stringType(),
14284
14333
  version: unionType([stringType(), numberType()]).optional(),
14285
14334
  description: stringType().optional(),
14286
- artifacts: arrayType(SchemaYamlArtifactSchema$1),
14335
+ artifacts: arrayType(SchemaYamlArtifactSchema),
14287
14336
  apply: objectType({
14288
14337
  requires: arrayType(stringType()).optional(),
14289
14338
  tracks: stringType().optional(),
@@ -14291,8 +14340,8 @@ const SchemaYamlSchema$1 = objectType({
14291
14340
  }).optional()
14292
14341
  });
14293
14342
  function parseSchemaYamlInline(content) {
14294
- const raw$1 = (0, import_dist$1.parse)(content);
14295
- const parsed = SchemaYamlSchema$1.safeParse(raw$1);
14343
+ const raw$1 = (0, import_dist.parse)(content);
14344
+ const parsed = SchemaYamlSchema.safeParse(raw$1);
14296
14345
  if (!parsed.success) throw new Error(`Invalid schema.yaml: ${parsed.error.message}`);
14297
14346
  const { artifacts, apply, name, description, version } = parsed.data;
14298
14347
  const detail = {
@@ -16999,12 +17048,12 @@ function createMiddlewareFactory() {
16999
17048
  * @internal
17000
17049
  * Please note, `trpc-openapi` uses this function.
17001
17050
  */
17002
- function createInputMiddleware(parse$5) {
17051
+ function createInputMiddleware(parse$4) {
17003
17052
  const inputMiddleware = async function inputValidatorMiddleware(opts) {
17004
17053
  let parsedInput;
17005
17054
  const rawInput = await opts.getRawInput();
17006
17055
  try {
17007
- parsedInput = await parse$5(rawInput);
17056
+ parsedInput = await parse$4(rawInput);
17008
17057
  } catch (cause) {
17009
17058
  throw new TRPCError({
17010
17059
  code: "BAD_REQUEST",
@@ -17020,12 +17069,12 @@ function createInputMiddleware(parse$5) {
17020
17069
  /**
17021
17070
  * @internal
17022
17071
  */
17023
- function createOutputMiddleware(parse$5) {
17072
+ function createOutputMiddleware(parse$4) {
17024
17073
  const outputMiddleware = async function outputValidatorMiddleware({ next }) {
17025
17074
  const result = await next();
17026
17075
  if (!result.ok) return result;
17027
17076
  try {
17028
- const data = await parse$5(result.data);
17077
+ const data = await parse$4(result.data);
17029
17078
  return (0, import_objectSpread2$2.default)((0, import_objectSpread2$2.default)({}, result), {}, { data });
17030
17079
  } catch (cause) {
17031
17080
  throw new TRPCError({
@@ -20914,7 +20963,7 @@ var require_extension = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm
20914
20963
  * @return {Object} The parsed object
20915
20964
  * @public
20916
20965
  */
20917
- function parse$3(header) {
20966
+ function parse$2(header) {
20918
20967
  const offers = Object.create(null);
20919
20968
  let params = Object.create(null);
20920
20969
  let mustUnescape = false;
@@ -21029,7 +21078,7 @@ var require_extension = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm
21029
21078
  }
21030
21079
  module.exports = {
21031
21080
  format: format$2,
21032
- parse: parse$3
21081
+ parse: parse$2
21033
21082
  };
21034
21083
  }) });
21035
21084
 
@@ -21050,7 +21099,7 @@ var require_websocket = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm
21050
21099
  const { isBlob } = require_validation();
21051
21100
  const { BINARY_TYPES, EMPTY_BUFFER, GUID: GUID$1, kForOnEventAttribute, kListener, kStatusCode, kWebSocket: kWebSocket$1, NOOP } = require_constants();
21052
21101
  const { EventTarget: { addEventListener: addEventListener$1, removeEventListener } } = require_event_target();
21053
- const { format: format$1, parse: parse$2 } = require_extension();
21102
+ const { format: format$1, parse: parse$1 } = require_extension();
21054
21103
  const { toBuffer } = require_buffer_util();
21055
21104
  const closeTimeout = 30 * 1e3;
21056
21105
  const kAborted = Symbol("kAborted");
@@ -21713,7 +21762,7 @@ var require_websocket = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pnpm
21713
21762
  }
21714
21763
  let extensions;
21715
21764
  try {
21716
- extensions = parse$2(secWebSocketExtensions);
21765
+ extensions = parse$1(secWebSocketExtensions);
21717
21766
  } catch (err) {
21718
21767
  abortHandshake$1(websocket, socket, "Invalid Sec-WebSocket-Extensions header");
21719
21768
  return;
@@ -22127,7 +22176,7 @@ var require_subprotocol = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pn
22127
22176
  * @return {Set} The subprotocol names
22128
22177
  * @public
22129
22178
  */
22130
- function parse$1(header) {
22179
+ function parse(header) {
22131
22180
  const protocols = /* @__PURE__ */ new Set();
22132
22181
  let start = -1;
22133
22182
  let end = -1;
@@ -22153,7 +22202,7 @@ var require_subprotocol = /* @__PURE__ */ __commonJS$1({ "../../node_modules/.pn
22153
22202
  protocols.add(protocol);
22154
22203
  return protocols;
22155
22204
  }
22156
- module.exports = { parse: parse$1 };
22205
+ module.exports = { parse };
22157
22206
  }) });
22158
22207
 
22159
22208
  //#endregion
@@ -22927,86 +22976,7 @@ function createPtyWebSocketHandler(ptyManager) {
22927
22976
  }
22928
22977
 
22929
22978
  //#endregion
22930
- //#region ../search/dist/worker-source-BxMlTiAB.mjs
22931
- const DEFAULT_LIMIT = 50;
22932
- const MAX_LIMIT = 200;
22933
- const SNIPPET_SIZE = 180;
22934
- function normalizeText(input) {
22935
- return input.toLowerCase().replace(/\s+/g, " ").trim();
22936
- }
22937
- function splitTerms(query) {
22938
- return normalizeText(query).split(" ").map((term) => term.trim()).filter((term) => term.length > 0);
22939
- }
22940
- function toSearchIndexDocument(doc) {
22941
- return {
22942
- ...doc,
22943
- normalizedTitle: normalizeText(doc.title),
22944
- normalizedPath: normalizeText(doc.path),
22945
- normalizedContent: normalizeText(doc.content)
22946
- };
22947
- }
22948
- function buildSearchIndex(docs) {
22949
- return { documents: docs.map(toSearchIndexDocument) };
22950
- }
22951
- function resolveLimit(limit) {
22952
- if (typeof limit !== "number" || Number.isNaN(limit)) return DEFAULT_LIMIT;
22953
- return Math.min(MAX_LIMIT, Math.max(1, Math.trunc(limit)));
22954
- }
22955
- function isDocumentMatch(doc, terms) {
22956
- return terms.every((term) => doc.normalizedTitle.includes(term) || doc.normalizedPath.includes(term) || doc.normalizedContent.includes(term));
22957
- }
22958
- function scoreDocument(doc, terms) {
22959
- let score = 0;
22960
- for (const term of terms) {
22961
- if (doc.normalizedTitle.includes(term)) score += 30;
22962
- if (doc.normalizedPath.includes(term)) score += 20;
22963
- const contentIdx = doc.normalizedContent.indexOf(term);
22964
- if (contentIdx >= 0) {
22965
- score += 8;
22966
- if (contentIdx < 160) score += 4;
22967
- }
22968
- }
22969
- return score;
22970
- }
22971
- function createSnippet(content, terms) {
22972
- const source = content.trim();
22973
- if (!source) return "";
22974
- const normalizedSource = normalizeText(source);
22975
- let matchIndex = -1;
22976
- for (const term of terms) {
22977
- const idx = normalizedSource.indexOf(term);
22978
- if (idx >= 0 && (matchIndex < 0 || idx < matchIndex)) matchIndex = idx;
22979
- }
22980
- if (matchIndex < 0) return source.slice(0, SNIPPET_SIZE);
22981
- const start = Math.max(0, matchIndex - Math.floor(SNIPPET_SIZE / 3));
22982
- const end = Math.min(source.length, start + SNIPPET_SIZE);
22983
- const prefix = start > 0 ? "..." : "";
22984
- const suffix = end < source.length ? "..." : "";
22985
- return `${prefix}${source.slice(start, end)}${suffix}`;
22986
- }
22987
- function searchIndex(index, query) {
22988
- const terms = splitTerms(query.query);
22989
- if (terms.length === 0) return [];
22990
- const hits = [];
22991
- for (const doc of index.documents) {
22992
- if (!isDocumentMatch(doc, terms)) continue;
22993
- hits.push({
22994
- documentId: doc.id,
22995
- kind: doc.kind,
22996
- title: doc.title,
22997
- href: doc.href,
22998
- path: doc.path,
22999
- score: scoreDocument(doc, terms),
23000
- snippet: createSnippet(doc.content, terms),
23001
- updatedAt: doc.updatedAt
23002
- });
23003
- }
23004
- hits.sort((a, b) => {
23005
- if (b.score !== a.score) return b.score - a.score;
23006
- return b.updatedAt - a.updatedAt;
23007
- });
23008
- return hits.slice(0, resolveLimit(query.limit));
23009
- }
22979
+ //#region ../search/dist/worker-source-CMPZlh9-.mjs
23010
22980
  const SearchDocumentKindSchema = enumType([
23011
22981
  "spec",
23012
22982
  "change",
@@ -23076,15 +23046,128 @@ const sharedRuntimeSource = String.raw`
23076
23046
  const DEFAULT_LIMIT = 50;
23077
23047
  const MAX_LIMIT = 200;
23078
23048
  const SNIPPET_SIZE = 180;
23079
- const normalizeText = ${normalizeText.toString()};
23080
- const splitTerms = ${splitTerms.toString()};
23081
- const toSearchIndexDocument = ${toSearchIndexDocument.toString()};
23082
- const buildSearchIndex = ${buildSearchIndex.toString()};
23083
- const resolveLimit = ${resolveLimit.toString()};
23084
- const isDocumentMatch = ${isDocumentMatch.toString()};
23085
- const scoreDocument = ${scoreDocument.toString()};
23086
- const createSnippet = ${createSnippet.toString()};
23087
- const searchIndex = ${searchIndex.toString()};
23049
+
23050
+ function normalizeText(input) {
23051
+ return String(input || '')
23052
+ .toLowerCase()
23053
+ .replace(/\s+/g, ' ')
23054
+ .trim();
23055
+ }
23056
+
23057
+ function splitTerms(query) {
23058
+ return normalizeText(query)
23059
+ .split(' ')
23060
+ .map((term) => term.trim())
23061
+ .filter((term) => term.length > 0);
23062
+ }
23063
+
23064
+ function toSearchIndexDocument(doc) {
23065
+ return {
23066
+ id: doc.id,
23067
+ kind: doc.kind,
23068
+ title: doc.title,
23069
+ href: doc.href,
23070
+ path: doc.path,
23071
+ content: doc.content,
23072
+ updatedAt: doc.updatedAt,
23073
+ normalizedTitle: normalizeText(doc.title),
23074
+ normalizedPath: normalizeText(doc.path),
23075
+ normalizedContent: normalizeText(doc.content),
23076
+ };
23077
+ }
23078
+
23079
+ function buildSearchIndex(docs) {
23080
+ return {
23081
+ documents: Array.isArray(docs) ? docs.map(toSearchIndexDocument) : [],
23082
+ };
23083
+ }
23084
+
23085
+ function resolveLimit(limit) {
23086
+ if (typeof limit !== 'number' || Number.isNaN(limit)) return DEFAULT_LIMIT;
23087
+ return Math.min(MAX_LIMIT, Math.max(1, Math.trunc(limit)));
23088
+ }
23089
+
23090
+ function isDocumentMatch(doc, terms) {
23091
+ return terms.every(
23092
+ (term) =>
23093
+ doc.normalizedTitle.includes(term) ||
23094
+ doc.normalizedPath.includes(term) ||
23095
+ doc.normalizedContent.includes(term)
23096
+ );
23097
+ }
23098
+
23099
+ function scoreDocument(doc, terms) {
23100
+ let score = 0;
23101
+
23102
+ for (const term of terms) {
23103
+ if (doc.normalizedTitle.includes(term)) score += 30;
23104
+ if (doc.normalizedPath.includes(term)) score += 20;
23105
+
23106
+ const contentIdx = doc.normalizedContent.indexOf(term);
23107
+ if (contentIdx >= 0) {
23108
+ score += 8;
23109
+ if (contentIdx < 160) score += 4;
23110
+ }
23111
+ }
23112
+
23113
+ return score;
23114
+ }
23115
+
23116
+ function createSnippet(content, terms) {
23117
+ const source = String(content || '').trim();
23118
+ if (!source) return '';
23119
+
23120
+ const normalizedSource = normalizeText(source);
23121
+ let matchIndex = -1;
23122
+
23123
+ for (const term of terms) {
23124
+ const idx = normalizedSource.indexOf(term);
23125
+ if (idx >= 0 && (matchIndex < 0 || idx < matchIndex)) {
23126
+ matchIndex = idx;
23127
+ }
23128
+ }
23129
+
23130
+ if (matchIndex < 0) {
23131
+ return source.slice(0, SNIPPET_SIZE);
23132
+ }
23133
+
23134
+ const start = Math.max(0, matchIndex - Math.floor(SNIPPET_SIZE / 3));
23135
+ const end = Math.min(source.length, start + SNIPPET_SIZE);
23136
+
23137
+ const prefix = start > 0 ? '...' : '';
23138
+ const suffix = end < source.length ? '...' : '';
23139
+ return prefix + source.slice(start, end) + suffix;
23140
+ }
23141
+
23142
+ function searchIndex(index, query) {
23143
+ const terms = splitTerms(query && query.query ? query.query : '');
23144
+ if (terms.length === 0) return [];
23145
+
23146
+ const hits = [];
23147
+
23148
+ for (const doc of index.documents) {
23149
+ if (!isDocumentMatch(doc, terms)) continue;
23150
+
23151
+ hits.push({
23152
+ documentId: doc.id,
23153
+ kind: doc.kind,
23154
+ title: doc.title,
23155
+ href: doc.href,
23156
+ path: doc.path,
23157
+ score: scoreDocument(doc, terms),
23158
+ snippet: createSnippet(doc.content, terms),
23159
+ updatedAt: doc.updatedAt,
23160
+ });
23161
+ }
23162
+
23163
+ hits.sort((a, b) => {
23164
+ if (b.score !== a.score) return b.score - a.score;
23165
+ return b.updatedAt - a.updatedAt;
23166
+ });
23167
+
23168
+ return hits.slice(0, resolveLimit(query ? query.limit : undefined));
23169
+ }
23170
+
23088
23171
  let index = buildSearchIndex([]);
23089
23172
 
23090
23173
  function handleMessage(payload) {
@@ -23176,54 +23259,6 @@ function createCliStreamObservable(startStream) {
23176
23259
  });
23177
23260
  }
23178
23261
 
23179
- //#endregion
23180
- //#region ../server/src/opsx-schema.ts
23181
- var import_dist = require_dist();
23182
- const SchemaYamlArtifactSchema = objectType({
23183
- id: stringType(),
23184
- generates: stringType(),
23185
- description: stringType().optional(),
23186
- template: stringType().optional(),
23187
- instruction: stringType().optional(),
23188
- requires: arrayType(stringType()).optional()
23189
- });
23190
- const SchemaYamlSchema = objectType({
23191
- name: stringType(),
23192
- version: unionType([stringType(), numberType()]).optional(),
23193
- description: stringType().optional(),
23194
- artifacts: arrayType(SchemaYamlArtifactSchema),
23195
- apply: objectType({
23196
- requires: arrayType(stringType()).optional(),
23197
- tracks: stringType().optional(),
23198
- instruction: stringType().optional()
23199
- }).optional()
23200
- });
23201
- function parseSchemaYaml(content) {
23202
- const raw$1 = (0, import_dist.parse)(content);
23203
- const parsed = SchemaYamlSchema.safeParse(raw$1);
23204
- if (!parsed.success) throw new Error(`Invalid schema.yaml: ${parsed.error.message}`);
23205
- const { artifacts, apply, name, description, version } = parsed.data;
23206
- const detail = {
23207
- name,
23208
- description,
23209
- version,
23210
- artifacts: artifacts.map((artifact) => ({
23211
- id: artifact.id,
23212
- outputPath: artifact.generates,
23213
- description: artifact.description,
23214
- template: artifact.template,
23215
- instruction: artifact.instruction,
23216
- requires: artifact.requires ?? []
23217
- })),
23218
- applyRequires: apply?.requires ?? [],
23219
- applyTracks: apply?.tracks,
23220
- applyInstruction: apply?.instruction
23221
- };
23222
- const validated = SchemaDetailSchema.safeParse(detail);
23223
- if (!validated.success) throw new Error(`Invalid schema detail: ${validated.error.message}`);
23224
- return validated.data;
23225
- }
23226
-
23227
23262
  //#endregion
23228
23263
  //#region ../server/src/reactive-kv.ts
23229
23264
  /**
@@ -23351,20 +23386,6 @@ function requireChangeId(changeId) {
23351
23386
  function ensureEditableSource(source, label) {
23352
23387
  if (source === "package") throw new Error(`${label} is read-only (package source)`);
23353
23388
  }
23354
- function parseCliJson(raw$1, schema$6, label) {
23355
- const trimmed = raw$1.trim();
23356
- if (!trimmed) throw new Error(`${label} returned empty output`);
23357
- let parsed;
23358
- try {
23359
- parsed = JSON.parse(trimmed);
23360
- } catch (err) {
23361
- const message = err instanceof Error ? err.message : String(err);
23362
- throw new Error(`${label} returned invalid JSON: ${message}`);
23363
- }
23364
- const result = schema$6.safeParse(parsed);
23365
- if (!result.success) throw new Error(`${label} returned unexpected JSON: ${result.error.message}`);
23366
- return result.data;
23367
- }
23368
23389
  function resolveEntryPath(root, entryPath) {
23369
23390
  const normalizedRoot = resolve$1(root);
23370
23391
  const resolvedPath = resolve$1(normalizedRoot, entryPath);
@@ -23372,153 +23393,62 @@ function resolveEntryPath(root, entryPath) {
23372
23393
  if (resolvedPath !== normalizedRoot && !resolvedPath.startsWith(rootPrefix)) throw new Error("Invalid path: outside schema root");
23373
23394
  return resolvedPath;
23374
23395
  }
23375
- function toRelativePath(root, absolutePath) {
23376
- return relative$1(root, absolutePath).split(sep).join("/");
23377
- }
23378
- async function readEntriesUnderRoot(root) {
23379
- if (!(await reactiveStat(root))?.isDirectory) return [];
23380
- const collectEntries = async (dir) => {
23381
- const names = await reactiveReadDir(dir, { includeHidden: false });
23382
- const entries = [];
23383
- for (const name of names) {
23384
- const fullPath = join$1(dir, name);
23385
- const statInfo = await reactiveStat(fullPath);
23386
- if (!statInfo) continue;
23387
- const relativePath = toRelativePath(root, fullPath);
23388
- if (statInfo.isDirectory) {
23389
- entries.push({
23390
- path: relativePath,
23391
- type: "directory"
23392
- });
23393
- entries.push(...await collectEntries(fullPath));
23394
- } else {
23395
- const content = await reactiveReadFile(fullPath);
23396
- const size = content ? Buffer.byteLength(content, "utf-8") : void 0;
23397
- entries.push({
23398
- path: relativePath,
23399
- type: "file",
23400
- content: content ?? void 0,
23401
- size
23402
- });
23403
- }
23404
- }
23405
- return entries;
23406
- };
23407
- return collectEntries(root);
23408
- }
23409
- async function touchOpsxProjectDeps(projectDir) {
23410
- const openspecDir = join$1(projectDir, "openspec");
23411
- await reactiveReadFile(join$1(openspecDir, "config.yaml"));
23412
- const schemaRoot = join$1(openspecDir, "schemas");
23413
- const schemaDirs = await reactiveReadDir(schemaRoot, {
23414
- directoriesOnly: true,
23415
- includeHidden: true
23416
- });
23417
- await Promise.all(schemaDirs.map((name) => reactiveReadFile(join$1(schemaRoot, name, "schema.yaml"))));
23418
- await reactiveReadDir(join$1(openspecDir, "changes"), {
23419
- directoriesOnly: true,
23420
- includeHidden: true,
23421
- exclude: ["archive"]
23422
- });
23423
- }
23424
- async function touchOpsxChangeDeps(projectDir, changeId) {
23425
- const changeDir = join$1(projectDir, "openspec", "changes", changeId);
23426
- await reactiveReadDir(changeDir, { includeHidden: true });
23427
- await reactiveReadFile(join$1(changeDir, ".openspec.yaml"));
23428
- }
23429
- async function readGlobArtifactFiles(projectDir, changeId, outputPath) {
23430
- return (await readEntriesUnderRoot(join$1(projectDir, "openspec", "changes", changeId))).filter((entry) => entry.type === "file" && matchesGlob(entry.path, outputPath)).map((entry) => ({
23431
- path: entry.path,
23432
- type: "file",
23433
- content: entry.content ?? ""
23434
- }));
23435
- }
23436
23396
  async function fetchOpsxStatus(ctx, input) {
23437
23397
  const changeId = requireChangeId(input.change);
23438
- await touchOpsxProjectDeps(ctx.projectDir);
23439
- await touchOpsxChangeDeps(ctx.projectDir, changeId);
23440
- const args = [
23441
- "status",
23442
- "--json",
23443
- "--change",
23444
- changeId
23445
- ];
23446
- if (input.schema) args.push("--schema", input.schema);
23447
- const result = await ctx.cliExecutor.execute(args);
23448
- if (!result.success) throw new Error(result.stderr || `openspec status failed (exit ${result.exitCode ?? "null"})`);
23449
- const status = parseCliJson(result.stdout, ChangeStatusSchema, "openspec status");
23450
- const changeRelDir = `openspec/changes/${changeId}`;
23451
- for (const artifact of status.artifacts) artifact.relativePath = `${changeRelDir}/${artifact.outputPath}`;
23452
- return status;
23398
+ await ctx.kernel.waitForWarmup();
23399
+ await ctx.kernel.ensureStatus(changeId, input.schema);
23400
+ return ctx.kernel.getStatus(changeId, input.schema);
23453
23401
  }
23454
23402
  async function fetchOpsxStatusList(ctx) {
23455
- const changeIds = await reactiveReadDir(join$1(ctx.projectDir, "openspec", "changes"), {
23456
- directoriesOnly: true,
23457
- includeHidden: false,
23458
- exclude: ["archive"]
23459
- });
23460
- return await Promise.all(changeIds.map((changeId) => fetchOpsxStatus(ctx, { change: changeId })));
23403
+ await ctx.kernel.waitForWarmup();
23404
+ await ctx.kernel.ensureStatusList();
23405
+ return ctx.kernel.getStatusList();
23461
23406
  }
23462
23407
  async function fetchOpsxInstructions(ctx, input) {
23463
23408
  const changeId = requireChangeId(input.change);
23464
- await touchOpsxProjectDeps(ctx.projectDir);
23465
- await touchOpsxChangeDeps(ctx.projectDir, changeId);
23466
- const args = [
23467
- "instructions",
23468
- input.artifact,
23469
- "--json",
23470
- "--change",
23471
- changeId
23472
- ];
23473
- if (input.schema) args.push("--schema", input.schema);
23474
- const result = await ctx.cliExecutor.execute(args);
23475
- if (!result.success) throw new Error(result.stderr || `openspec instructions failed (exit ${result.exitCode ?? "null"})`);
23476
- return parseCliJson(result.stdout, ArtifactInstructionsSchema, "openspec instructions");
23409
+ await ctx.kernel.waitForWarmup();
23410
+ await ctx.kernel.ensureInstructions(changeId, input.artifact, input.schema);
23411
+ return ctx.kernel.getInstructions(changeId, input.artifact, input.schema);
23477
23412
  }
23478
23413
  async function fetchOpsxApplyInstructions(ctx, input) {
23479
23414
  const changeId = requireChangeId(input.change);
23480
- await touchOpsxProjectDeps(ctx.projectDir);
23481
- await touchOpsxChangeDeps(ctx.projectDir, changeId);
23482
- const args = [
23483
- "instructions",
23484
- "apply",
23485
- "--json",
23486
- "--change",
23487
- changeId
23488
- ];
23489
- if (input.schema) args.push("--schema", input.schema);
23490
- const result = await ctx.cliExecutor.execute(args);
23491
- if (!result.success) throw new Error(result.stderr || `openspec instructions apply failed (exit ${result.exitCode ?? "null"})`);
23492
- return parseCliJson(result.stdout, ApplyInstructionsSchema, "openspec instructions apply");
23415
+ await ctx.kernel.waitForWarmup();
23416
+ await ctx.kernel.ensureApplyInstructions(changeId, input.schema);
23417
+ return ctx.kernel.getApplyInstructions(changeId, input.schema);
23493
23418
  }
23494
- async function fetchOpsxSchemas(ctx) {
23495
- await touchOpsxProjectDeps(ctx.projectDir);
23496
- const result = await ctx.cliExecutor.schemas();
23497
- if (!result.success) throw new Error(result.stderr || `openspec schemas failed (exit ${result.exitCode ?? "null"})`);
23498
- return parseCliJson(result.stdout, arrayType(SchemaInfoSchema), "openspec schemas");
23419
+ async function fetchOpsxConfigBundle(ctx) {
23420
+ await ctx.kernel.ensureSchemas();
23421
+ const schemas$1 = ctx.kernel.getSchemas();
23422
+ for (const schema$6 of schemas$1) {
23423
+ ctx.kernel.ensureSchemaDetail(schema$6.name).catch(() => {});
23424
+ ctx.kernel.ensureSchemaResolution(schema$6.name).catch(() => {});
23425
+ }
23426
+ const schemaDetails = {};
23427
+ const schemaResolutions = {};
23428
+ for (const schema$6 of schemas$1) {
23429
+ schemaDetails[schema$6.name] = ctx.kernel.peekSchemaDetail(schema$6.name);
23430
+ schemaResolutions[schema$6.name] = ctx.kernel.peekSchemaResolution(schema$6.name);
23431
+ }
23432
+ return {
23433
+ schemas: schemas$1,
23434
+ schemaDetails,
23435
+ schemaResolutions
23436
+ };
23499
23437
  }
23500
23438
  async function fetchOpsxSchemaResolution(ctx, name) {
23501
- await touchOpsxProjectDeps(ctx.projectDir);
23502
- const result = await ctx.cliExecutor.schemaWhich(name);
23503
- if (!result.success) throw new Error(result.stderr || `openspec schema which failed (exit ${result.exitCode ?? "null"})`);
23504
- return parseCliJson(result.stdout, SchemaResolutionSchema, "openspec schema which");
23439
+ await ctx.kernel.waitForWarmup();
23440
+ await ctx.kernel.ensureSchemaResolution(name);
23441
+ return ctx.kernel.getSchemaResolution(name);
23505
23442
  }
23506
23443
  async function fetchOpsxTemplates(ctx, schema$6) {
23507
- await touchOpsxProjectDeps(ctx.projectDir);
23508
- const result = await ctx.cliExecutor.templates(schema$6);
23509
- if (!result.success) throw new Error(result.stderr || `openspec templates failed (exit ${result.exitCode ?? "null"})`);
23510
- return parseCliJson(result.stdout, TemplatesSchema, "openspec templates");
23444
+ await ctx.kernel.waitForWarmup();
23445
+ await ctx.kernel.ensureTemplates(schema$6);
23446
+ return ctx.kernel.getTemplates(schema$6);
23511
23447
  }
23512
23448
  async function fetchOpsxTemplateContents(ctx, schema$6) {
23513
- const templates = await fetchOpsxTemplates(ctx, schema$6);
23514
- const entries = await Promise.all(Object.entries(templates).map(async ([artifactId, info]) => {
23515
- return [artifactId, {
23516
- content: await reactiveReadFile(info.path),
23517
- path: info.path,
23518
- source: info.source
23519
- }];
23520
- }));
23521
- return Object.fromEntries(entries);
23449
+ await ctx.kernel.waitForWarmup();
23450
+ await ctx.kernel.ensureTemplateContents(schema$6);
23451
+ return ctx.kernel.getTemplateContents(schema$6);
23522
23452
  }
23523
23453
  /**
23524
23454
  * Spec router - spec CRUD operations
@@ -23908,11 +23838,11 @@ const opsxRouter = router({
23908
23838
  })).subscription(({ ctx, input }) => {
23909
23839
  return createReactiveSubscription(() => fetchOpsxApplyInstructions(ctx, input));
23910
23840
  }),
23911
- schemas: publicProcedure.query(async ({ ctx }) => {
23912
- return fetchOpsxSchemas(ctx);
23841
+ configBundle: publicProcedure.query(async ({ ctx }) => {
23842
+ return fetchOpsxConfigBundle(ctx);
23913
23843
  }),
23914
- subscribeSchemas: publicProcedure.subscription(({ ctx }) => {
23915
- return createReactiveSubscription(() => fetchOpsxSchemas(ctx));
23844
+ subscribeConfigBundle: publicProcedure.subscription(({ ctx }) => {
23845
+ return createReactiveSubscription(() => fetchOpsxConfigBundle(ctx));
23916
23846
  }),
23917
23847
  templates: publicProcedure.input(objectType({ schema: stringType().optional() }).optional()).query(async ({ ctx, input }) => {
23918
23848
  return fetchOpsxTemplates(ctx, input?.schema);
@@ -23926,53 +23856,34 @@ const opsxRouter = router({
23926
23856
  subscribeTemplateContents: publicProcedure.input(objectType({ schema: stringType().optional() }).optional()).subscription(({ ctx, input }) => {
23927
23857
  return createReactiveSubscription(() => fetchOpsxTemplateContents(ctx, input?.schema));
23928
23858
  }),
23929
- schemaResolution: publicProcedure.input(objectType({ name: stringType() })).query(async ({ ctx, input }) => {
23930
- return fetchOpsxSchemaResolution(ctx, input.name);
23931
- }),
23932
- subscribeSchemaResolution: publicProcedure.input(objectType({ name: stringType() })).subscription(({ ctx, input }) => {
23933
- return createReactiveSubscription(() => fetchOpsxSchemaResolution(ctx, input.name));
23934
- }),
23935
- schemaDetail: publicProcedure.input(objectType({ name: stringType() })).query(async ({ ctx, input }) => {
23936
- await touchOpsxProjectDeps(ctx.projectDir);
23937
- const schemaPath = join$1((await fetchOpsxSchemaResolution(ctx, input.name)).path, "schema.yaml");
23938
- const content = await reactiveReadFile(schemaPath);
23939
- if (!content) throw new Error(`schema.yaml not found at ${schemaPath}`);
23940
- return parseSchemaYaml(content);
23941
- }),
23942
- subscribeSchemaDetail: publicProcedure.input(objectType({ name: stringType() })).subscription(({ ctx, input }) => {
23943
- return createReactiveSubscription(async () => {
23944
- await touchOpsxProjectDeps(ctx.projectDir);
23945
- const schemaPath = join$1((await fetchOpsxSchemaResolution(ctx, input.name)).path, "schema.yaml");
23946
- const content = await reactiveReadFile(schemaPath);
23947
- if (!content) throw new Error(`schema.yaml not found at ${schemaPath}`);
23948
- return parseSchemaYaml(content);
23949
- });
23950
- }),
23951
23859
  schemaFiles: publicProcedure.input(objectType({ name: stringType() })).query(async ({ ctx, input }) => {
23952
- await touchOpsxProjectDeps(ctx.projectDir);
23953
- return readEntriesUnderRoot((await fetchOpsxSchemaResolution(ctx, input.name)).path);
23860
+ await ctx.kernel.waitForWarmup();
23861
+ await ctx.kernel.ensureSchemaFiles(input.name);
23862
+ return ctx.kernel.getSchemaFiles(input.name);
23954
23863
  }),
23955
23864
  subscribeSchemaFiles: publicProcedure.input(objectType({ name: stringType() })).subscription(({ ctx, input }) => {
23956
23865
  return createReactiveSubscription(async () => {
23957
- await touchOpsxProjectDeps(ctx.projectDir);
23958
- return readEntriesUnderRoot((await fetchOpsxSchemaResolution(ctx, input.name)).path);
23866
+ await ctx.kernel.waitForWarmup();
23867
+ await ctx.kernel.ensureSchemaFiles(input.name);
23868
+ return ctx.kernel.getSchemaFiles(input.name);
23959
23869
  });
23960
23870
  }),
23961
23871
  schemaYaml: publicProcedure.input(objectType({ name: stringType() })).query(async ({ ctx, input }) => {
23962
- await touchOpsxProjectDeps(ctx.projectDir);
23963
- return reactiveReadFile(join$1((await fetchOpsxSchemaResolution(ctx, input.name)).path, "schema.yaml"));
23872
+ await ctx.kernel.waitForWarmup();
23873
+ await ctx.kernel.ensureSchemaYaml(input.name);
23874
+ return ctx.kernel.getSchemaYaml(input.name);
23964
23875
  }),
23965
23876
  subscribeSchemaYaml: publicProcedure.input(objectType({ name: stringType() })).subscription(({ ctx, input }) => {
23966
23877
  return createReactiveSubscription(async () => {
23967
- await touchOpsxProjectDeps(ctx.projectDir);
23968
- return reactiveReadFile(join$1((await fetchOpsxSchemaResolution(ctx, input.name)).path, "schema.yaml"));
23878
+ await ctx.kernel.waitForWarmup();
23879
+ await ctx.kernel.ensureSchemaYaml(input.name);
23880
+ return ctx.kernel.getSchemaYaml(input.name);
23969
23881
  });
23970
23882
  }),
23971
23883
  writeSchemaYaml: publicProcedure.input(objectType({
23972
23884
  name: stringType(),
23973
23885
  content: stringType()
23974
23886
  })).mutation(async ({ ctx, input }) => {
23975
- await touchOpsxProjectDeps(ctx.projectDir);
23976
23887
  const resolution = await fetchOpsxSchemaResolution(ctx, input.name);
23977
23888
  ensureEditableSource(resolution.source, "schema.yaml");
23978
23889
  const schemaPath = join$1(resolution.path, "schema.yaml");
@@ -23985,7 +23896,6 @@ const opsxRouter = router({
23985
23896
  path: stringType(),
23986
23897
  content: stringType()
23987
23898
  })).mutation(async ({ ctx, input }) => {
23988
- await touchOpsxProjectDeps(ctx.projectDir);
23989
23899
  const resolution = await fetchOpsxSchemaResolution(ctx, input.schema);
23990
23900
  ensureEditableSource(resolution.source, "schema file");
23991
23901
  if (!input.path.trim()) throw new Error("path is required");
@@ -23999,7 +23909,6 @@ const opsxRouter = router({
23999
23909
  path: stringType(),
24000
23910
  content: stringType().optional()
24001
23911
  })).mutation(async ({ ctx, input }) => {
24002
- await touchOpsxProjectDeps(ctx.projectDir);
24003
23912
  const resolution = await fetchOpsxSchemaResolution(ctx, input.schema);
24004
23913
  ensureEditableSource(resolution.source, "schema file");
24005
23914
  if (!input.path.trim()) throw new Error("path is required");
@@ -24012,7 +23921,6 @@ const opsxRouter = router({
24012
23921
  schema: stringType(),
24013
23922
  path: stringType()
24014
23923
  })).mutation(async ({ ctx, input }) => {
24015
- await touchOpsxProjectDeps(ctx.projectDir);
24016
23924
  const resolution = await fetchOpsxSchemaResolution(ctx, input.schema);
24017
23925
  ensureEditableSource(resolution.source, "schema directory");
24018
23926
  if (!input.path.trim()) throw new Error("path is required");
@@ -24023,7 +23931,6 @@ const opsxRouter = router({
24023
23931
  schema: stringType(),
24024
23932
  path: stringType()
24025
23933
  })).mutation(async ({ ctx, input }) => {
24026
- await touchOpsxProjectDeps(ctx.projectDir);
24027
23934
  const resolution = await fetchOpsxSchemaResolution(ctx, input.schema);
24028
23935
  ensureEditableSource(resolution.source, "schema entry");
24029
23936
  if (!input.path.trim()) throw new Error("path is required");
@@ -24039,26 +23946,18 @@ const opsxRouter = router({
24039
23946
  schema: stringType(),
24040
23947
  artifactId: stringType()
24041
23948
  })).query(async ({ ctx, input }) => {
24042
- const info = (await fetchOpsxTemplates(ctx, input.schema))[input.artifactId];
23949
+ const info = (await fetchOpsxTemplateContents(ctx, input.schema))[input.artifactId];
24043
23950
  if (!info) throw new Error(`Template not found for ${input.schema}:${input.artifactId}`);
24044
- return {
24045
- content: await reactiveReadFile(info.path),
24046
- path: info.path,
24047
- source: info.source
24048
- };
23951
+ return info;
24049
23952
  }),
24050
23953
  subscribeTemplateContent: publicProcedure.input(objectType({
24051
23954
  schema: stringType(),
24052
23955
  artifactId: stringType()
24053
23956
  })).subscription(({ ctx, input }) => {
24054
23957
  return createReactiveSubscription(async () => {
24055
- const info = (await fetchOpsxTemplates(ctx, input.schema))[input.artifactId];
23958
+ const info = (await fetchOpsxTemplateContents(ctx, input.schema))[input.artifactId];
24056
23959
  if (!info) throw new Error(`Template not found for ${input.schema}:${input.artifactId}`);
24057
- return {
24058
- content: await reactiveReadFile(info.path),
24059
- path: info.path,
24060
- source: info.source
24061
- };
23960
+ return info;
24062
23961
  });
24063
23962
  }),
24064
23963
  writeTemplateContent: publicProcedure.input(objectType({
@@ -24074,7 +23973,6 @@ const opsxRouter = router({
24074
23973
  return { success: true };
24075
23974
  }),
24076
23975
  deleteSchema: publicProcedure.input(objectType({ name: stringType() })).mutation(async ({ ctx, input }) => {
24077
- await touchOpsxProjectDeps(ctx.projectDir);
24078
23976
  const resolution = await fetchOpsxSchemaResolution(ctx, input.name);
24079
23977
  ensureEditableSource(resolution.source, "schema");
24080
23978
  await rm(resolution.path, {
@@ -24084,11 +23982,15 @@ const opsxRouter = router({
24084
23982
  return { success: true };
24085
23983
  }),
24086
23984
  projectConfig: publicProcedure.query(async ({ ctx }) => {
24087
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "config.yaml"));
23985
+ await ctx.kernel.waitForWarmup();
23986
+ await ctx.kernel.ensureProjectConfig();
23987
+ return ctx.kernel.getProjectConfig();
24088
23988
  }),
24089
23989
  subscribeProjectConfig: publicProcedure.subscription(({ ctx }) => {
24090
23990
  return createReactiveSubscription(async () => {
24091
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "config.yaml"));
23991
+ await ctx.kernel.waitForWarmup();
23992
+ await ctx.kernel.ensureProjectConfig();
23993
+ return ctx.kernel.getProjectConfig();
24092
23994
  });
24093
23995
  }),
24094
23996
  writeProjectConfig: publicProcedure.input(objectType({ content: stringType() })).mutation(async ({ ctx, input }) => {
@@ -24098,55 +24000,63 @@ const opsxRouter = router({
24098
24000
  return { success: true };
24099
24001
  }),
24100
24002
  listChanges: publicProcedure.query(async ({ ctx }) => {
24101
- return reactiveReadDir(join$1(ctx.projectDir, "openspec", "changes"), {
24102
- directoriesOnly: true,
24103
- exclude: ["archive"],
24104
- includeHidden: false
24105
- });
24003
+ await ctx.kernel.waitForWarmup();
24004
+ await ctx.kernel.ensureChangeIds();
24005
+ return ctx.kernel.getChangeIds();
24106
24006
  }),
24107
24007
  subscribeChanges: publicProcedure.subscription(({ ctx }) => {
24108
24008
  return createReactiveSubscription(async () => {
24109
- return reactiveReadDir(join$1(ctx.projectDir, "openspec", "changes"), {
24110
- directoriesOnly: true,
24111
- exclude: ["archive"],
24112
- includeHidden: false
24113
- });
24009
+ await ctx.kernel.waitForWarmup();
24010
+ await ctx.kernel.ensureChangeIds();
24011
+ return ctx.kernel.getChangeIds();
24114
24012
  });
24115
24013
  }),
24116
24014
  changeMetadata: publicProcedure.input(objectType({ changeId: stringType() })).query(async ({ ctx, input }) => {
24117
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "changes", input.changeId, ".openspec.yaml"));
24015
+ await ctx.kernel.waitForWarmup();
24016
+ await ctx.kernel.ensureChangeMetadata(input.changeId);
24017
+ return ctx.kernel.getChangeMetadata(input.changeId);
24118
24018
  }),
24119
24019
  subscribeChangeMetadata: publicProcedure.input(objectType({ changeId: stringType() })).subscription(({ ctx, input }) => {
24120
24020
  return createReactiveSubscription(async () => {
24121
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "changes", input.changeId, ".openspec.yaml"));
24021
+ await ctx.kernel.waitForWarmup();
24022
+ await ctx.kernel.ensureChangeMetadata(input.changeId);
24023
+ return ctx.kernel.getChangeMetadata(input.changeId);
24122
24024
  });
24123
24025
  }),
24124
24026
  readArtifactOutput: publicProcedure.input(objectType({
24125
24027
  changeId: stringType(),
24126
24028
  outputPath: stringType()
24127
24029
  })).query(async ({ ctx, input }) => {
24128
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "changes", input.changeId, input.outputPath));
24030
+ await ctx.kernel.waitForWarmup();
24031
+ await ctx.kernel.ensureArtifactOutput(input.changeId, input.outputPath);
24032
+ return ctx.kernel.getArtifactOutput(input.changeId, input.outputPath);
24129
24033
  }),
24130
24034
  subscribeArtifactOutput: publicProcedure.input(objectType({
24131
24035
  changeId: stringType(),
24132
24036
  outputPath: stringType()
24133
24037
  })).subscription(({ ctx, input }) => {
24134
24038
  return createReactiveSubscription(async () => {
24135
- return reactiveReadFile(join$1(ctx.projectDir, "openspec", "changes", input.changeId, input.outputPath));
24039
+ await ctx.kernel.waitForWarmup();
24040
+ await ctx.kernel.ensureArtifactOutput(input.changeId, input.outputPath);
24041
+ return ctx.kernel.getArtifactOutput(input.changeId, input.outputPath);
24136
24042
  });
24137
24043
  }),
24138
24044
  readGlobArtifactFiles: publicProcedure.input(objectType({
24139
24045
  changeId: stringType(),
24140
24046
  outputPath: stringType()
24141
24047
  })).query(async ({ ctx, input }) => {
24142
- return readGlobArtifactFiles(ctx.projectDir, input.changeId, input.outputPath);
24048
+ await ctx.kernel.waitForWarmup();
24049
+ await ctx.kernel.ensureGlobArtifactFiles(input.changeId, input.outputPath);
24050
+ return ctx.kernel.getGlobArtifactFiles(input.changeId, input.outputPath);
24143
24051
  }),
24144
24052
  subscribeGlobArtifactFiles: publicProcedure.input(objectType({
24145
24053
  changeId: stringType(),
24146
24054
  outputPath: stringType()
24147
24055
  })).subscription(({ ctx, input }) => {
24148
24056
  return createReactiveSubscription(async () => {
24149
- return readGlobArtifactFiles(ctx.projectDir, input.changeId, input.outputPath);
24057
+ await ctx.kernel.waitForWarmup();
24058
+ await ctx.kernel.ensureGlobArtifactFiles(input.changeId, input.outputPath);
24059
+ return ctx.kernel.getGlobArtifactFiles(input.changeId, input.outputPath);
24150
24060
  });
24151
24061
  }),
24152
24062
  writeArtifactOutput: publicProcedure.input(objectType({