@oevery/rsp 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/chunk-AUZYUJ46.mjs +418 -0
  2. package/dist/chunk-DNRGBQS7.mjs +108 -0
  3. package/dist/chunk-LGDCIQYL.mjs +725 -0
  4. package/dist/chunk-P3KO3GZW.mjs +1023 -0
  5. package/dist/{chunk-HFSTLCCK.mjs → chunk-VDRXFKBP.mjs} +133 -1800
  6. package/dist/cli.mjs +286 -294
  7. package/dist/client-U2PN3VS4.mjs +108 -0
  8. package/dist/{entry-RIJQ2X46.mjs → entry-NDASTAI5.mjs} +13 -9
  9. package/dist/viewer/NOTICE.txt +299 -0
  10. package/dist/viewer/app.css +2 -0
  11. package/dist/viewer/app.js +670 -0
  12. package/dist/viewer/chunks/abnfDiagram-S7VZAUFO-K5EOZOEF.js +1 -0
  13. package/dist/viewer/chunks/architecture-WOLXFQ4H-UAT5D5BF.js +1 -0
  14. package/dist/viewer/chunks/architectureDiagram-YGSQEFNW-UNPSYM2L.js +36 -0
  15. package/dist/viewer/chunks/blockDiagram-APKKGZFW-2F7TTPAV.js +140 -0
  16. package/dist/viewer/chunks/bpmnIcons-APHXDYXF-ZWPFFN3O.js +1 -0
  17. package/dist/viewer/chunks/c4Diagram-KJ2TOQU5-KNLN6CME.js +38 -0
  18. package/dist/viewer/chunks/chunk-274PZN6B.js +1 -0
  19. package/dist/viewer/chunks/chunk-2VGDQLQD.js +1 -0
  20. package/dist/viewer/chunks/chunk-33XESOCS.js +1 -0
  21. package/dist/viewer/chunks/chunk-3ZSL2TGQ.js +1 -0
  22. package/dist/viewer/chunks/chunk-432I4U3B.js +1 -0
  23. package/dist/viewer/chunks/chunk-4PJNGS3V.js +1 -0
  24. package/dist/viewer/chunks/chunk-54NLSLTF.js +9 -0
  25. package/dist/viewer/chunks/chunk-6QRHYJ5Q.js +1 -0
  26. package/dist/viewer/chunks/chunk-6RCFKBVR.js +1 -0
  27. package/dist/viewer/chunks/chunk-6Y2HP7DC.js +213 -0
  28. package/dist/viewer/chunks/chunk-7MAT7NHP.js +1 -0
  29. package/dist/viewer/chunks/chunk-AKHBD6LT.js +2 -0
  30. package/dist/viewer/chunks/chunk-CZIM56BV.js +1 -0
  31. package/dist/viewer/chunks/chunk-DN4Y7LXJ.js +1 -0
  32. package/dist/viewer/chunks/chunk-E2UQN267.js +1 -0
  33. package/dist/viewer/chunks/chunk-GBARLDDT.js +1 -0
  34. package/dist/viewer/chunks/chunk-H4YEV7VR.js +1 -0
  35. package/dist/viewer/chunks/chunk-HUVVDQHZ.js +1 -0
  36. package/dist/viewer/chunks/chunk-IAKC32WV.js +72 -0
  37. package/dist/viewer/chunks/chunk-JTW4SY4L.js +1 -0
  38. package/dist/viewer/chunks/chunk-JZV675LF.js +1 -0
  39. package/dist/viewer/chunks/chunk-KDUDYTWO.js +1 -0
  40. package/dist/viewer/chunks/chunk-KHX3A5RZ.js +331 -0
  41. package/dist/viewer/chunks/chunk-KPXJJSUR.js +15 -0
  42. package/dist/viewer/chunks/chunk-LEGNM6PH.js +1 -0
  43. package/dist/viewer/chunks/chunk-LYY4ZY72.js +1 -0
  44. package/dist/viewer/chunks/chunk-MKDEK2LU.js +1 -0
  45. package/dist/viewer/chunks/chunk-MYJRFART.js +129 -0
  46. package/dist/viewer/chunks/chunk-NUXZBURC.js +1 -0
  47. package/dist/viewer/chunks/chunk-NXHT5I2L.js +1 -0
  48. package/dist/viewer/chunks/chunk-OF62XRVM.js +62 -0
  49. package/dist/viewer/chunks/chunk-ONCOEVBS.js +1 -0
  50. package/dist/viewer/chunks/chunk-P44SH3OO.js +1 -0
  51. package/dist/viewer/chunks/chunk-PDXKDBIX.js +1 -0
  52. package/dist/viewer/chunks/chunk-PHKIAKHS.js +1 -0
  53. package/dist/viewer/chunks/chunk-PJDMAGPE.js +2 -0
  54. package/dist/viewer/chunks/chunk-RC2NPHSX.js +88 -0
  55. package/dist/viewer/chunks/chunk-T6DM5RSK.js +10 -0
  56. package/dist/viewer/chunks/chunk-U5STX66M.js +2 -0
  57. package/dist/viewer/chunks/chunk-UIAJQPOF.js +1 -0
  58. package/dist/viewer/chunks/chunk-UX2S3LP3.js +1 -0
  59. package/dist/viewer/chunks/chunk-VEMTQQ7Y.js +2 -0
  60. package/dist/viewer/chunks/chunk-WKCPBR3C.js +1 -0
  61. package/dist/viewer/chunks/chunk-WMQ4Y2MS.js +32 -0
  62. package/dist/viewer/chunks/chunk-YPWIQAHX.js +3 -0
  63. package/dist/viewer/chunks/chunk-Z4ZDIMO2.js +136 -0
  64. package/dist/viewer/chunks/chunk-ZATQCNXH.js +1 -0
  65. package/dist/viewer/chunks/chunk-ZE5RDJX6.js +1 -0
  66. package/dist/viewer/chunks/chunk-ZO62R4L2.js +1 -0
  67. package/dist/viewer/chunks/classDiagram-v2-L25IHNXF-5F2M2CZ4.js +217 -0
  68. package/dist/viewer/chunks/cose-bilkent-JH36ORCC-S56HJ5WN.js +1 -0
  69. package/dist/viewer/chunks/cynefin-EF2NZ3EQ-6WY2NCLE.js +1 -0
  70. package/dist/viewer/chunks/cynefinDiagram-L36ESFBY-DE6PZNQA.js +62 -0
  71. package/dist/viewer/chunks/dagre-SPEB5RXH-QEOTKFV2.js +4 -0
  72. package/dist/viewer/chunks/diagram-3B7GL73J-RZPIU7FY.js +200 -0
  73. package/dist/viewer/chunks/diagram-DNEMPZML-YD26TJKC.js +24 -0
  74. package/dist/viewer/chunks/diagram-L3MUGCDN-TJUEX4QI.js +41 -0
  75. package/dist/viewer/chunks/diagram-LA4NIPWU-3PUQS6UW.js +24 -0
  76. package/dist/viewer/chunks/diagram-MHCOC4E2-YBTBD4PG.js +3 -0
  77. package/dist/viewer/chunks/diagram-XPFHEONP-VF2TQBNR.js +30 -0
  78. package/dist/viewer/chunks/ebnfDiagram-UZSYDL2S-QE7DIEME.js +1 -0
  79. package/dist/viewer/chunks/elk-XV6XMXQE-X5OZRIL3.js +27 -0
  80. package/dist/viewer/chunks/erDiagram-EYBAPDEH-5B2S7VB4.js +99 -0
  81. package/dist/viewer/chunks/eventmodeling-K75KTNOO-CHCQYZBI.js +1 -0
  82. package/dist/viewer/chunks/flowDiagram-MALGAFMO-XJFC5NTN.js +1 -0
  83. package/dist/viewer/chunks/ganttDiagram-23REXITY-TUUZ3QYO.js +292 -0
  84. package/dist/viewer/chunks/gitGraph-VSP46ZUC-VFZPJQ6A.js +1 -0
  85. package/dist/viewer/chunks/gitGraphDiagram-STJD7YCW-4CVV5LSH.js +106 -0
  86. package/dist/viewer/chunks/info-OHQRW6UA-P4744SJ6.js +1 -0
  87. package/dist/viewer/chunks/infoDiagram-KBXO4MBG-Q2WYYNNN.js +2 -0
  88. package/dist/viewer/chunks/ishikawaDiagram-M35NCXHK-PLQPTX2U.js +70 -0
  89. package/dist/viewer/chunks/journeyDiagram-OPLOXDXO-FB73RE6F.js +139 -0
  90. package/dist/viewer/chunks/kanban-definition-BZKZHSQY-6FU4TXYJ.js +89 -0
  91. package/dist/viewer/chunks/katex-IN4S3RHS.js +257 -0
  92. package/dist/viewer/chunks/mindmap-definition-I2QAS2VK-ZQ36ABVW.js +98 -0
  93. package/dist/viewer/chunks/packet-JDAUHWVQ-NYXIQQVA.js +1 -0
  94. package/dist/viewer/chunks/pegDiagram-FD4XPPHP-5XXVT6XN.js +1 -0
  95. package/dist/viewer/chunks/pie-XZMESJXO-32CUE6KZ.js +1 -0
  96. package/dist/viewer/chunks/pieDiagram-J4AKIIQI-WRTBDFM5.js +39 -0
  97. package/dist/viewer/chunks/quadrantDiagram-XTYBLID2-YPBDQIAK.js +7 -0
  98. package/dist/viewer/chunks/radar-ABXABTNO-272FILRO.js +1 -0
  99. package/dist/viewer/chunks/railroad-I3PHUGI6-6EGAH4XA.js +1 -0
  100. package/dist/viewer/chunks/railroad-abnf-LNEFI6M7-G6E7ATER.js +1 -0
  101. package/dist/viewer/chunks/railroad-ebnf-DWYD2UWJ-MR4P6BDR.js +1 -0
  102. package/dist/viewer/chunks/railroad-peg-JR7BVNR7-WXLQUGUO.js +1 -0
  103. package/dist/viewer/chunks/railroadDiagram-MRQ6NCDL-XHZQ2BLY.js +1 -0
  104. package/dist/viewer/chunks/requirementDiagram-Y7LWUY3S-W5FHRRML.js +84 -0
  105. package/dist/viewer/chunks/sankeyDiagram-WGJFYUXA-OJJIRVTI.js +40 -0
  106. package/dist/viewer/chunks/sequenceDiagram-5NDRBG5M-D6T4DRNG.js +169 -0
  107. package/dist/viewer/chunks/sizeCapture-INFHLROL-WL3FTUJX.js +1 -0
  108. package/dist/viewer/chunks/stateDiagram-v2-FJ4FJNEA-LAXL7KGG.js +291 -0
  109. package/dist/viewer/chunks/swimlanes-UMQ2AFYF-XIJBD726.js +1 -0
  110. package/dist/viewer/chunks/swimlanesDiagram-OMPLPG4O-7O7MHFW7.js +8 -0
  111. package/dist/viewer/chunks/timeline-definition-SEUHKTQE-BAZQA47I.js +120 -0
  112. package/dist/viewer/chunks/treeView-D4JQ5SDB-6YMDAAPA.js +1 -0
  113. package/dist/viewer/chunks/treemap-SAJKECNS-2X573PPS.js +1 -0
  114. package/dist/viewer/chunks/usecaseDiagram-AFA6YXN4-4YCEMWJB.js +370 -0
  115. package/dist/viewer/chunks/vennDiagram-NNMJR3RB-GEMROLAE.js +34 -0
  116. package/dist/viewer/chunks/wardley-7MLQ67FV-DGTGHYYC.js +1 -0
  117. package/dist/viewer/chunks/wardleyDiagram-S7YFUSEH-K4HVD3SS.js +78 -0
  118. package/dist/viewer/chunks/xychartDiagram-GGNKY7IX-HVLWCUEO.js +7 -0
  119. package/dist/viewer/mermaid.js +12 -0
  120. package/dist/viewer-build.json +1 -0
  121. package/dist/viewer-service.mjs +607 -0
  122. package/package.json +27 -8
  123. package/skills/rsp/SKILL.md +13 -10
  124. package/skills/rsp/references/architecture.md +39 -0
  125. package/skills/rsp/references/closeout.md +4 -4
  126. package/skills/rsp/references/durable-review.md +6 -9
  127. package/skills/rsp/references/focus-continuation.md +6 -2
  128. package/skills/rsp/references/setup-repair.md +11 -6
  129. package/skills/rsp/references/work-model.md +14 -4
  130. package/skills/rsp-commit/SKILL.md +2 -2
  131. package/skills/rsp-doc/SKILL.md +13 -10
  132. package/skills/rsp-doc/references/skill-authoring.md +2 -2
  133. package/skills/rsp-implement/SKILL.md +16 -12
  134. package/skills/rsp-review/SKILL.md +12 -12
  135. package/skills/rsp-review/references/code-review.md +11 -5
  136. package/skills/rsp-review/references/document-review.md +8 -10
  137. package/skills/rsp-shape/SKILL.md +3 -1
  138. package/skills/rsp-shape/references/planning.md +4 -4
  139. package/skills/rsp-verify/SKILL.md +9 -14
  140. package/skills/rsp-doc/references/artifact-lenses.md +0 -43
  141. package/skills/rsp-review/references/structural-review.md +0 -41
package/dist/cli.mjs CHANGED
@@ -1,7 +1,78 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- ARCHIVES_DIR,
3
+ ARCHITECTURE_FILE,
4
+ PROJECT_VERSION_PATH,
5
+ SOURCE_INVOCATION,
6
+ compareVersions,
7
+ exactInvocation,
8
+ guardProjectVersion,
9
+ isExactVersion,
10
+ queryArchitecture,
11
+ readProjectRuntime,
12
+ readProjectVersion,
13
+ selectProjectRuntime
14
+ } from "./chunk-AUZYUJ46.mjs";
15
+ import {
4
16
  ArchiveHistoryError,
17
+ GROUP_BRIEF_FILENAME,
18
+ GROUP_REOPEN_COMPLETION_PREFIX,
19
+ HISTORY_DEFAULT_LIMIT,
20
+ HISTORY_MAX_LIMIT,
21
+ IssueRelationshipError,
22
+ WorkRefError,
23
+ buildDurableReviewGuidance,
24
+ collectArchiveReadiness,
25
+ createIssueRelationship,
26
+ generateGroupBriefContent,
27
+ getDurableReviewCandidateTargets,
28
+ getGroupReopenEvidence,
29
+ hasArchivedGroupBrief,
30
+ historyInspectionComplete,
31
+ inspectArchiveHistory,
32
+ inspectArchiveTree,
33
+ inspectChangeDependencies,
34
+ inspectChangeGroups,
35
+ inspectFocusTree,
36
+ inspectProjectStatus,
37
+ inspectWorkTree,
38
+ normalizeExecutableWorkRef,
39
+ normalizeWorkRefSegment,
40
+ parseIssueRelationships,
41
+ projectDependencyForest,
42
+ projectSpecsDetail,
43
+ projectSpecsSearch,
44
+ projectSpecsTree,
45
+ queryArchiveHistory,
46
+ readArchiveHistoryDetail,
47
+ resolveArchiveDirectory,
48
+ resolveExecutableChange,
49
+ resolveFocusMarkerPath,
50
+ resolveWorkRef,
51
+ selectArchiveHistoryRecord,
52
+ selectArchivedGroupBrief,
53
+ toArchiveReadinessOutput
54
+ } from "./chunk-VDRXFKBP.mjs";
55
+ import {
56
+ SPECS_DEFAULT_RESULT_LIMIT,
57
+ SPECS_DETAIL_CONTENT_CODE_POINTS,
58
+ SPECS_MAX_RESULT_LIMIT,
59
+ SpecsQueryError,
60
+ cleanupEmptyParentDirs,
61
+ detectProjectName,
62
+ emitJson,
63
+ guardRspInitialized,
64
+ inspectRspInitialization,
65
+ inspectSpecs,
66
+ inspectUnsupportedRules,
67
+ isRecognizedGeneratedSpecsIndex,
68
+ isValidSpecName,
69
+ normalizeLogicalPath,
70
+ specsInspectionComplete,
71
+ toErrorMessage,
72
+ walkMarkdownFiles
73
+ } from "./chunk-LGDCIQYL.mjs";
74
+ import {
75
+ ARCHIVES_DIR,
5
76
  CHANGES_DIR,
6
77
  CHANGE_DOCUMENT_SCHEMA,
7
78
  CONFIG_PATH,
@@ -9,11 +80,6 @@ import {
9
80
  DocumentSectionCardinalityError,
10
81
  FOCUS_DIR,
11
82
  GROUP_BRIEF_DOCUMENT_SCHEMA,
12
- GROUP_BRIEF_FILENAME,
13
- GROUP_REOPEN_COMPLETION_PREFIX,
14
- HISTORY_DEFAULT_LIMIT,
15
- HISTORY_MAX_LIMIT,
16
- IssueRelationshipError,
17
83
  LOCK_PATH,
18
84
  MAX_FOCUS_CAPSULE_BYTES,
19
85
  ManagedPathError,
@@ -21,94 +87,45 @@ import {
21
87
  PKG_ROOT,
22
88
  RSP_DIR,
23
89
  RSP_RULES_PATH,
24
- SPECS_DEFAULT_RESULT_LIMIT,
25
- SPECS_DETAIL_CONTENT_CODE_POINTS,
26
- SPECS_MAX_RESULT_LIMIT,
27
- SpecsQueryError,
28
- WorkRefError,
29
90
  appendDocumentSectionItem,
30
- buildDurableReviewGuidance,
31
- cleanupEmptyParentDirs,
32
91
  clearConfigCache,
33
- collectArchiveReadiness,
34
92
  countCheckboxes,
35
- createIssueRelationship,
36
93
  detectDeltaSections,
37
- detectProjectName,
38
- emitJson,
39
94
  ensureManagedFile,
40
95
  generateConfigTemplate,
41
- generateGroupBriefContent,
42
96
  getDocumentSectionDefinitionByHeading,
43
97
  getDocumentSectionMarkdown,
44
98
  getDocumentSections,
45
99
  getDocumentTitles,
46
- getDurableReviewCandidateTargets,
47
- getGroupReopenEvidence,
48
100
  getVersion,
49
101
  getVisibleBodyLines,
50
- guardRspInitialized,
51
- hasArchivedGroupBrief,
52
102
  hasMeaningfulBlockers,
53
- historyInspectionComplete,
54
- inspectArchiveHistory,
55
- inspectArchiveTree,
56
- inspectChangeDependencies,
57
- inspectChangeGroups,
58
- inspectFocusTree,
59
103
  inspectManagedDirectory,
60
104
  inspectManagedFile,
61
105
  inspectManagedFileTree,
62
- inspectProjectStatus,
63
106
  inspectRspConfig,
64
- inspectRspInitialization,
65
- inspectSpecs,
66
- inspectUnsupportedRules,
67
- inspectWorkTree,
68
- isRecognizedGeneratedSpecsIndex,
69
- isValidSpecName,
70
107
  loadRspConfig,
71
108
  markdownProse,
72
109
  markdownText,
73
110
  markdownTopLevelComments,
74
- normalizeExecutableWorkRef,
75
- normalizeLogicalPath,
76
- normalizeWorkRefSegment,
77
111
  parseFrontmatter,
78
- parseIssueRelationships,
79
112
  parseMarkdown,
80
113
  parseRspDocument,
81
114
  parseScenarios,
82
115
  pc,
83
- projectDependencyForest,
84
- projectSpecsDetail,
85
- projectSpecsSearch,
86
- projectSpecsTree,
87
- queryArchiveHistory,
88
- readArchiveHistoryDetail,
89
116
  renderDocumentSectionHeading,
90
117
  renderDocumentTitle,
91
118
  requireManagedDirectory,
92
119
  requireManagedFile,
93
- resolveArchiveDirectory,
94
120
  resolveDecisionRecordsPath,
95
- resolveExecutableChange,
96
- resolveFocusMarkerPath,
97
121
  resolveKinds,
98
122
  resolveLanguagePolicy,
99
123
  resolveManagedDirectoryChain,
100
124
  resolveRequiredSections,
101
- resolveWorkRef,
102
125
  resolveWorkflowPolicy,
103
- selectArchiveHistoryRecord,
104
- selectArchivedGroupBrief,
105
- specsInspectionComplete,
106
- toArchiveReadinessOutput,
107
- toErrorMessage,
108
126
  validateDecisionRecordsFilesystemPath,
109
- walkMarkdownFiles,
110
127
  writeManagedFile
111
- } from "./chunk-HFSTLCCK.mjs";
128
+ } from "./chunk-P3KO3GZW.mjs";
112
129
 
113
130
  // src/cli.ts
114
131
  import { resolve as resolve2 } from "path";
@@ -117,6 +134,7 @@ import { runMain } from "citty";
117
134
 
118
135
  // src/cli/capabilities.ts
119
136
  var CLI_COMMAND_CAPABILITIES = {
137
+ "architecture": { json: true, compact: true },
120
138
  "config": { json: true, compact: true },
121
139
  "status": { json: true, compact: true },
122
140
  "show": { json: true, compact: true },
@@ -150,10 +168,56 @@ function supportsCompact(command) {
150
168
  }
151
169
 
152
170
  // src/cli/registry.ts
153
- import { defineCommand as defineCommand5 } from "citty";
171
+ import { defineCommand as defineCommand6 } from "citty";
154
172
 
155
- // src/cli/commands/inspection.ts
173
+ // src/cli/commands/architecture.ts
156
174
  import { defineCommand } from "citty";
175
+ var architectureCommand = defineCommand({
176
+ meta: { name: "architecture", description: "Read full or selected architecture structure without document bodies" },
177
+ args: { node: { type: "string", description: "Node and descendants" }, view: { type: "string", description: "Explicit view selection" }, ...compactJsonArgs },
178
+ async run({ args }) {
179
+ const unknown = Object.keys(args).filter((key) => !["node", "view", "json", "compact", "_"].includes(key));
180
+ if (unknown.length || args._.length)
181
+ throw new Error(`Unsupported architecture options/arguments: ${[...unknown, ...args._].join(", ")}`);
182
+ const result = await queryArchitecture({ node: args.node, view: args.view });
183
+ if (args.json) {
184
+ console.log(JSON.stringify(result, null, args.compact ? void 0 : 2));
185
+ } else {
186
+ console.log(`Architecture: ${result.configured ? result.source.root : "not configured"}
187
+ Selection: ${result.selection.kind}${result.selection.id ? ` ${result.selection.id}` : ""}`);
188
+ for (const node of result.nodes) {
189
+ console.log(`${node.boundary ? "[boundary] " : ""}${node.id}: ${node.title} \u2014 ${node.description}${node.parent ? ` (parent: ${node.parent})` : ""}`);
190
+ for (const binding of node.bindings) console.log(` ${binding.file}${binding.headings ? ` > ${binding.headings.join(" > ")}` : ""} (scope: ${binding.scope}; ${binding.inherited ? `inherited from ${binding.origin}` : `direct on ${binding.origin}`})`);
191
+ }
192
+ for (const edge of result.relations) console.log(`Relation ${edge.id}: ${edge.source} -> ${edge.target} [${edge.type}]${edge.label ? ` ${edge.label}` : ""}: ${edge.description}`);
193
+ for (const view of result.views) {
194
+ console.log(`View ${view.id}: ${view.title} (owner: ${view.node}; include: ${view.include.join(", ")})`);
195
+ if (view.relationTypes || view.relationIds || view.boundary)
196
+ console.log(` Filters: types=${view.relationTypes?.join(", ") ?? "*"}; relations=${view.relationIds?.join(", ") ?? "*"}; boundary=${view.boundary ?? "include"}`);
197
+ for (const participant of view.scenario?.participants ?? [])
198
+ console.log(` Participant ${participant.id}: ${participant.node}${participant.title ? ` (${participant.title})` : ""}`);
199
+ view.scenario?.steps.forEach((step, index) => console.log(` ${index + 1}. ${step.id}: ${step.source} -> ${step.target} [${step.type}] ${step.label}${step.replyTo ? ` (reply to ${step.replyTo})` : ""}${step.description ? ` \u2014 ${step.description}` : ""}`));
200
+ }
201
+ for (const diagnostic of result.diagnostics) console.log(`${diagnostic.code}: ${diagnostic.message}`);
202
+ if (result.configured)
203
+ console.log(`Source: ${result.source.file} @ ${result.source.revision}`);
204
+ }
205
+ }
206
+ });
207
+ var viewCommand = defineCommand({
208
+ meta: { name: "view", description: "Open the shared local architecture viewer, inspect or stop its service" },
209
+ args: { action: { type: "positional", required: false, description: "status or stop; omit to open" }, open: { type: "boolean", default: true, description: "Open browser (use --no-open to print URL only)" } },
210
+ async run({ args }) {
211
+ const unknown = Object.keys(args).filter((key) => !["action", "open", "_"].includes(key));
212
+ if (unknown.length || args._.length > 1 || args.action && !args.open)
213
+ throw new Error("rsp view accepts only an optional status/stop action or --no-open");
214
+ const { runView } = await import("./client-U2PN3VS4.mjs");
215
+ await runView(args.action, args.open);
216
+ }
217
+ });
218
+
219
+ // src/cli/commands/inspection.ts
220
+ import { defineCommand as defineCommand2 } from "citty";
157
221
 
158
222
  // src/commands/check.ts
159
223
  import { readFile } from "fs/promises";
@@ -255,7 +319,6 @@ function inspectChangeDocument(content, options) {
255
319
  }
256
320
 
257
321
  // src/core/focus-capsule.ts
258
- import { Buffer } from "buffer";
259
322
  import { TextDecoder } from "util";
260
323
  var FOCUS_CAPSULE_VERSION = "<!-- rsp-focus:v1 -->";
261
324
  var LEGACY_WARNING = "legacy focus capsule has no structured recovery projection";
@@ -273,15 +336,6 @@ function inspectFocusCapsuleBytes(bytes) {
273
336
  } catch {
274
337
  return { kind: "invalid", code: "focus_capsule_invalid_utf8", message: "focus capsule must contain valid UTF-8" };
275
338
  }
276
- if (Buffer.byteLength(content, "utf-8") > MAX_FOCUS_CAPSULE_BYTES) {
277
- return {
278
- kind: "invalid",
279
- code: "focus_capsule_too_large",
280
- message: `focus capsule exceeds ${MAX_FOCUS_CAPSULE_BYTES} UTF-8 bytes`
281
- };
282
- }
283
- if (content.length === 0)
284
- return { kind: "empty", content: "" };
285
339
  return parseFocusCapsule(content);
286
340
  }
287
341
  function parseFocusCapsule(content) {
@@ -637,109 +691,8 @@ async function showConfig() {
637
691
 
638
692
  // src/commands/doctor.ts
639
693
  import { existsSync } from "fs";
640
- import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
641
- import { basename, join as join3, relative as relative2 } from "path";
642
-
643
- // src/core/project-version.ts
644
- import { readFile as readFile2, realpath } from "fs/promises";
645
- import { join } from "path";
646
- var PROJECT_VERSION_PATH = ".rsp/version";
647
- var PROJECT_SOURCE_PATH = ".rsp/source";
648
- var SOURCE_INVOCATION = "mise exec -- node dist/cli.mjs";
649
- function isExactVersion(value) {
650
- return /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*))*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?$/i.test(value);
651
- }
652
- function exactInvocation(version) {
653
- if (!isExactVersion(version))
654
- throw new Error(`Invalid exact RSP version: ${version}`);
655
- return `npx -y @oevery/rsp@${version}`;
656
- }
657
- async function readProjectVersion(projectRoot = ".") {
658
- const directory = inspectManagedDirectory(join(projectRoot, RSP_DIR), "RSP root", { allowMissing: true });
659
- if (directory.issue)
660
- throw directory.issue;
661
- if (!directory.exists)
662
- return null;
663
- const path = join(projectRoot, PROJECT_VERSION_PATH);
664
- const inspection = inspectManagedFile(path, "project CLI version", { allowMissing: true });
665
- if (inspection.issue)
666
- throw inspection.issue;
667
- if (!inspection.exists)
668
- return null;
669
- const version = (await readFile2(path, "utf8")).trim();
670
- if (!isExactVersion(version))
671
- throw new Error(`${PROJECT_VERSION_PATH} must contain one exact package version, not a tag or range`);
672
- return version;
673
- }
674
- async function readProjectRuntime(projectRoot = ".") {
675
- const version = await readProjectVersion(projectRoot);
676
- const source = inspectManagedFile(join(projectRoot, PROJECT_SOURCE_PATH), "project source selection", { allowMissing: true });
677
- if (source.issue)
678
- throw source.issue;
679
- if (!source.exists)
680
- return { mode: "package", version };
681
- if (version !== null)
682
- throw new Error(`${PROJECT_SOURCE_PATH} and ${PROJECT_VERSION_PATH} are mutually exclusive; explicitly select one runtime.`);
683
- if ((await readFile2(join(projectRoot, PROJECT_SOURCE_PATH), "utf8")).trim() !== ".")
684
- throw new Error(`${PROJECT_SOURCE_PATH} must contain . to select this RSP source checkout.`);
685
- if (await realpath(projectRoot) !== await realpath(PKG_ROOT))
686
- throw new Error(`Source mode requires this checkout's local CLI. Build here, then use ${SOURCE_INVOCATION} <command>; a registry package or another checkout cannot substitute.`);
687
- const sourceDirectory = inspectManagedDirectory(join(projectRoot, "src"), "RSP source directory");
688
- const sourceEntry = inspectManagedFile(join(projectRoot, "src/cli.ts"), "RSP source entry");
689
- if (sourceDirectory.issue || sourceEntry.issue)
690
- throw sourceDirectory.issue ?? sourceEntry.issue;
691
- return { mode: "source" };
692
- }
693
- async function selectProjectRuntime(operation = "ordinary") {
694
- const version = await getVersion();
695
- exactInvocation(version);
696
- const selected = await readProjectRuntime();
697
- if (selected.mode === "source")
698
- return { mode: "source", version };
699
- if (selected.version && selected.version !== version && operation !== "update") {
700
- throw new Error(`Project pins RSP ${selected.version}; running CLI is ${version}. Use ${exactInvocation(selected.version)} <command>. To migrate deliberately, inspect the target version and run ${exactInvocation(version)} update.`);
701
- }
702
- if (selected.version && operation === "update" && compareVersions(version, selected.version) < 0)
703
- throw new Error(`Downgrading RSP from ${selected.version} to ${version} is unsupported. Use ${exactInvocation(selected.version)} <command>.`);
704
- return { mode: "package", version };
705
- }
706
- function compareVersions(left, right) {
707
- const parts = (value) => {
708
- const [core, ...pre] = value.split("+", 1)[0].split("-");
709
- return { core: core.split(".").map(BigInt), pre: pre.length ? pre.join("-").split(".") : [] };
710
- };
711
- const a = parts(left);
712
- const b = parts(right);
713
- for (let i = 0; i < 3; i++) {
714
- if (a.core[i] !== b.core[i])
715
- return a.core[i] > b.core[i] ? 1 : -1;
716
- }
717
- if (!a.pre.length || !b.pre.length)
718
- return Number(!a.pre.length) - Number(!b.pre.length);
719
- for (let i = 0; i < Math.max(a.pre.length, b.pre.length); i++) {
720
- const x = a.pre[i];
721
- const y = b.pre[i];
722
- if (x === y)
723
- continue;
724
- if (x === void 0 || y === void 0)
725
- return x === void 0 ? -1 : 1;
726
- const nx = /^\d+$/.test(x);
727
- const ny = /^\d+$/.test(y);
728
- if (nx && ny)
729
- return BigInt(x) > BigInt(y) ? 1 : -1;
730
- if (nx !== ny)
731
- return nx ? -1 : 1;
732
- return x > y ? 1 : -1;
733
- }
734
- return 0;
735
- }
736
- async function guardProjectVersion(rawArgs) {
737
- if (rawArgs.some((arg) => ["--help", "-h"].includes(arg)) || rawArgs.length === 1 && ["--version", "-v"].includes(rawArgs[0]))
738
- return;
739
- if (["doctor", "config", "update"].includes(rawArgs[0] ?? ""))
740
- return;
741
- await selectProjectRuntime();
742
- }
694
+ import { readdir as readdir2, readFile as readFile3, stat } from "fs/promises";
695
+ import { basename, join as join2, relative as relative2 } from "path";
743
696
 
744
697
  // src/core/artifacts.ts
745
698
  var RSP_AGENTS_BEGIN = "<!-- rsp:begin -->";
@@ -802,8 +755,8 @@ ${changeSectionHeading("verify")}
802
755
  ### Optional
803
756
  - Manual or environment:
804
757
  - [ ] ${placeholder}
805
- - Coverage:
806
- - ${placeholder}
758
+ ### Conclusions
759
+ - ${placeholder}
807
760
 
808
761
  ${changeSectionHeading("blockers")}
809
762
  - none
@@ -853,8 +806,8 @@ ${changeSectionHeading("verify")}
853
806
  ### Optional
854
807
  - Manual or environment:
855
808
  - [ ] ${template.manualVerify}
856
- - Coverage:
857
- - ${placeholder}
809
+ ### Conclusions
810
+ - ${placeholder}
858
811
 
859
812
  ${changeSectionHeading("blockers")}
860
813
  - none
@@ -895,9 +848,9 @@ function changeSectionHeading(sectionId) {
895
848
  const guidance = {
896
849
  proposal: "State the intended outcome, why it matters, scope, and non-goals; do not narrate execution.",
897
850
  spec: "Describe the contract delta and acceptance conditions, referencing affected existing Specs; do not copy the full baseline or implementation steps.",
898
- design: "Explain the approach, responsibility boundaries, and necessary tradeoffs; keep simple changes brief and avoid repeating requirements or tasks.",
899
- tasks: "List checkable work and mark completion only after outcomes exist; prescribe order only where correctness, safety, or migration requires it.",
900
- verify: "Connect acceptance to verification methods; after execution retain actual results, gaps, and limits, not command transcripts.",
851
+ design: "Explain the current approach, boundaries, and necessary tradeoffs; replace obsolete plans while preserving decision reasons and useful outcome comparisons.",
852
+ tasks: "Keep current checkable work and actual completion; revise or reopen invalidated tasks within authorized scope. Do not append routine attempts, fixes, retries, or check runs.",
853
+ verify: "Use Required/Optional checklists and an optional short, non-nested Conclusions list only. Uncheck failed, unrun or invalidated evidence. Keep current limits, applicability conditions or required failure dispositions; replace stale conclusions. No prose paragraphs, tables, repeated results or repair history. Remove Conclusions when unnecessary.",
901
854
  blockers: "Name unresolved decisions or dependencies that prevent progress; use none when there are no blockers."
902
855
  };
903
856
  return `${renderDocumentSectionHeading(CHANGE_DOCUMENT_SCHEMA, sectionId)}
@@ -911,14 +864,13 @@ function renderRspAgentsBlock(runtime) {
911
864
 
912
865
  RSP tracks current work, stable specs, and archives under \`.rsp/\`.
913
866
 
914
- Read in order using supplied or confirmed paths; discover only missing paths or applicable ancestor instructions, without overlapping whole-tree scans:
867
+ Use supplied or confirmed paths; discover only missing paths or applicable ancestor instructions, without overlapping whole-tree scans:
915
868
  1. Nearest \`AGENTS.md\` for project or module instructions.
916
869
  2. Root \`CONTEXT.md\` if present, then the relevant nearest \`CONTEXT.md\` for domain language, relationships, and navigation. If a legacy \`CONTEXT-MAP.md\` remains, retain its relevant context and use Core's context-migration branch; discovery alone does not authorize migration.
917
- 3. Use the project \`rsp\` Skill at \`.agents/skills/rsp/SKILL.md\`; hosts may load it through Skill discovery or read it directly. Skills are the only workflow: if a required Skill is missing or unusable, stop dependent work and report the incomplete installation. Do not use retired Rules or install implicitly.
918
- 4. \`.rsp/focus.d/\`; marker paths form the open-work candidate set, while optional bounded Markdown content is recovery guidance only. For grouped work read the sibling Group Brief, then the explicitly selected child Change.
919
- 5. Only the relevant Specs and Decision Records under the configured authoritative path.
870
+ 3. Establish the request's scope, authority and existing owner. A clear bounded request selecting one capability with sufficient owner facts loads that project Skill directly from \`.agents/skills/\`, without a Core or Focus preflight. For tracked work read the selected Change; for grouped work read its sibling Group Brief first. Read only relevant Specs and Decision Records under the configured authoritative path.
871
+ 4. Load \`rsp\` at \`.agents/skills/rsp/SKILL.md\` for unresolved routing or ownership, actual cross-capability coordination, or lifecycle operations. Read \`.rsp/focus.d/\` only when needed to resolve or recover the owner; marker paths are open-work candidates and optional bounded Markdown is recovery guidance, not authority. An explicit WorkRef or the user's mentioned Change selects first; otherwise use current status and dependency evidence.
920
872
 
921
- If \`.rsp/focus.d/\` is empty or has several candidates, use an explicit WorkRef, the user's mentioned Change, or current status/dependency evidence to resolve the default action.
873
+ Direct capability invocation does not make tracked work untracked. Preserve existing Changes, required tracking prerequisites, Group dependencies, independent review and permission boundaries; missing prerequisites stop dependent work. Skills are the only workflow: hosts may discover them or read them directly, but a missing or unusable required Skill stops dependent work and must be reported as an incomplete installation. Do not use retired Rules or install implicitly.
922
874
  Do not treat \`.rsp/specs/\` or \`.rsp/changes/\` as replacements for nearest \`AGENTS.md\` or \`CONTEXT.md\`.
923
875
 
924
876
  ${selection}
@@ -1031,8 +983,8 @@ async function checkForUpdates(current) {
1031
983
 
1032
984
  // src/commands/skills.ts
1033
985
  import { lstatSync, realpathSync } from "fs";
1034
- import { chmod, copyFile, mkdir, mkdtemp, readdir, readFile as readFile3, rename, rm } from "fs/promises";
1035
- import { dirname, join as join2, relative } from "path";
986
+ import { chmod, copyFile, mkdir, mkdtemp, readdir, readFile as readFile2, rename, rm } from "fs/promises";
987
+ import { dirname, join, relative } from "path";
1036
988
  var DEFAULT_PACKAGED_SKILL_NAMES = [
1037
989
  "rsp",
1038
990
  "rsp-shape",
@@ -1057,7 +1009,7 @@ function unsupportedEntry(path, label) {
1057
1009
  return new ManagedPathError(path, `unsupported entry in the ${label} tree: ${path}`);
1058
1010
  }
1059
1011
  async function inspectPackagedSkills(packageRoot) {
1060
- const skillsRoot = join2(packageRoot, "skills");
1012
+ const skillsRoot = join(packageRoot, "skills");
1061
1013
  const rootInspection = inspectManagedDirectory(skillsRoot, "packaged Skills root");
1062
1014
  if (rootInspection.issue)
1063
1015
  throw rootInspection.issue;
@@ -1066,7 +1018,7 @@ async function inspectPackagedSkills(packageRoot) {
1066
1018
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
1067
1019
  if (entry.name.startsWith("."))
1068
1020
  continue;
1069
- const root = join2(skillsRoot, entry.name);
1021
+ const root = join(skillsRoot, entry.name);
1070
1022
  if (!entry.isDirectory())
1071
1023
  throw unsupportedEntry(root, "packaged Skills");
1072
1024
  const inspection = await inspectManagedFileTree(root, `packaged Skill ${entry.name}`, { includeHidden: true });
@@ -1118,14 +1070,14 @@ async function treesEqual(source, targetRoot) {
1118
1070
  if (source.files.length !== targetFiles.length || source.files.some((path, index) => path !== targetFiles[index]))
1119
1071
  return false;
1120
1072
  for (const path of source.files) {
1121
- const sourcePath = join2(source.root, path);
1122
- const targetPath = join2(targetRoot, path);
1073
+ const sourcePath = join(source.root, path);
1074
+ const targetPath = join(targetRoot, path);
1123
1075
  const [sourceStats, targetStats] = [lstatSync(sourcePath), lstatSync(targetPath)];
1124
1076
  if (!sourceStats.isFile() || !targetStats.isFile())
1125
1077
  throw unsupportedEntry(!sourceStats.isFile() ? sourcePath : targetPath, `Skill ${source.name}`);
1126
1078
  if ((sourceStats.mode & 511) !== (targetStats.mode & 511))
1127
1079
  return false;
1128
- const [sourceContent, targetContent] = await Promise.all([readFile3(sourcePath), readFile3(targetPath)]);
1080
+ const [sourceContent, targetContent] = await Promise.all([readFile2(sourcePath), readFile2(targetPath)]);
1129
1081
  if (!sourceContent.equals(targetContent))
1130
1082
  return false;
1131
1083
  }
@@ -1139,14 +1091,14 @@ async function inspectPackagedSkillInventory(options = {}) {
1139
1091
  const missingDefaults = DEFAULT_PACKAGED_SKILL_NAMES.filter((name) => !packagedNames.has(name));
1140
1092
  if (missingDefaults.length > 0)
1141
1093
  throw new Error(`packaged Skills missing default Skills: ${missingDefaults.join(", ")}`);
1142
- const manifest = JSON.parse(await readFile3(join2(packageRoot, "package.json"), "utf8"));
1094
+ const manifest = JSON.parse(await readFile2(join(packageRoot, "package.json"), "utf8"));
1143
1095
  if (typeof manifest.name !== "string" || typeof manifest.version !== "string")
1144
1096
  throw new Error("package.json must contain string name and version fields");
1145
1097
  const targetRoot = resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1146
1098
  const defaults = new Set(DEFAULT_PACKAGED_SKILL_NAMES);
1147
1099
  const skills = [];
1148
1100
  for (const skill of packagedSkills) {
1149
- const target = join2(targetRoot, skill.name);
1101
+ const target = join(targetRoot, skill.name);
1150
1102
  const targetStatus = inspectInventoryTarget(target);
1151
1103
  skills.push({
1152
1104
  name: skill.name,
@@ -1154,7 +1106,7 @@ async function inspectPackagedSkillInventory(options = {}) {
1154
1106
  status: targetStatus === "missing" ? "missing" : targetStatus === "divergent" ? isCanonicalSourceProjection(skill.root, target) ? "unchanged" : "divergent" : await treesEqual(skill, target) ? "unchanged" : "divergent"
1155
1107
  });
1156
1108
  }
1157
- const retired = RETIRED_PACKAGED_SKILL_NAMES.filter((name) => inspectInventoryTarget(join2(targetRoot, name)) !== "missing");
1109
+ const retired = RETIRED_PACKAGED_SKILL_NAMES.filter((name) => inspectInventoryTarget(join(targetRoot, name)) !== "missing");
1158
1110
  return {
1159
1111
  retired,
1160
1112
  package: { name: manifest.name, version: manifest.version },
@@ -1165,8 +1117,8 @@ async function inspectPackagedSkillInventory(options = {}) {
1165
1117
  async function copySkillTree(source, targetRoot) {
1166
1118
  await mkdir(targetRoot, { recursive: true });
1167
1119
  for (const path of source.files) {
1168
- const sourcePath = join2(source.root, path);
1169
- const targetPath = join2(targetRoot, path);
1120
+ const sourcePath = join(source.root, path);
1121
+ const targetPath = join(targetRoot, path);
1170
1122
  const stats = lstatSync(sourcePath);
1171
1123
  if (!stats.isFile())
1172
1124
  throw unsupportedEntry(sourcePath, `packaged Skill ${source.name}`);
@@ -1189,7 +1141,7 @@ async function updatePackagedSkills(options = {}) {
1189
1141
  const targetRoot = resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1190
1142
  const result = { installed: [], removed: [], unchanged: [], replaced: [] };
1191
1143
  for (const skill of skills) {
1192
- const target = join2(targetRoot, skill.name);
1144
+ const target = join(targetRoot, skill.name);
1193
1145
  if (isCanonicalSourceProjection(skill.root, target))
1194
1146
  result.unchanged.push(skill.name);
1195
1147
  else if (inspectTarget(target, skill.name) === "missing")
@@ -1200,35 +1152,35 @@ async function updatePackagedSkills(options = {}) {
1200
1152
  result.replaced.push(skill.name);
1201
1153
  }
1202
1154
  for (const name of RETIRED_PACKAGED_SKILL_NAMES) {
1203
- if (inspectTarget(join2(targetRoot, name), name) !== "missing")
1155
+ if (inspectTarget(join(targetRoot, name), name) !== "missing")
1204
1156
  result.removed.push(name);
1205
1157
  }
1206
1158
  if (options.dryRun || result.installed.length + result.replaced.length + result.removed.length === 0)
1207
1159
  return result;
1208
1160
  await mkdir(targetRoot, { recursive: true });
1209
1161
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1210
- const staging = await mkdtemp(join2(targetRoot, ".rsp-skills-"));
1162
+ const staging = await mkdtemp(join(targetRoot, ".rsp-skills-"));
1211
1163
  const completed = [];
1212
1164
  let failure2;
1213
1165
  try {
1214
1166
  for (const skill of skills) {
1215
1167
  if (!result.unchanged.includes(skill.name))
1216
- await copySkillTree(skill, join2(staging, skill.name));
1168
+ await copySkillTree(skill, join(staging, skill.name));
1217
1169
  }
1218
1170
  for (const name of result.removed) {
1219
1171
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1220
- inspectTarget(join2(targetRoot, name), name);
1221
- await rm(join2(targetRoot, name), { recursive: true, force: true });
1172
+ inspectTarget(join(targetRoot, name), name);
1173
+ await rm(join(targetRoot, name), { recursive: true, force: true });
1222
1174
  completed.push(`removed ${name}`);
1223
1175
  }
1224
1176
  for (const skill of skills) {
1225
1177
  if (result.unchanged.includes(skill.name))
1226
1178
  continue;
1227
1179
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1228
- const target = join2(targetRoot, skill.name);
1180
+ const target = join(targetRoot, skill.name);
1229
1181
  inspectTarget(target, skill.name);
1230
1182
  await rm(target, { recursive: true, force: true });
1231
- await renamePath(join2(staging, skill.name), target);
1183
+ await renamePath(join(staging, skill.name), target);
1232
1184
  completed.push(`installed ${skill.name}`);
1233
1185
  }
1234
1186
  } catch (error) {
@@ -1275,14 +1227,16 @@ async function runDoctor(options = {}) {
1275
1227
  hint: "Use Core context migration. Retain relevant legacy context until an authorized merge updates CONTEXT.md and active references; update does not migrate or delete it."
1276
1228
  });
1277
1229
  }
1278
- await checkSpecsTree(checks, reportRuntime);
1279
1230
  await checkArchiveNaming(checks);
1280
- const decisionRecordsConfigValid = await checkConfigSemantics(checks, reportRuntime);
1281
- if (decisionRecordsConfigValid) {
1231
+ const configValid = await checkConfigSemantics(checks, reportRuntime);
1232
+ if (configValid) {
1233
+ await checkSpecsTree(checks, reportRuntime);
1282
1234
  await checkDecisionRecordsDirectory(checks, reportRuntime);
1283
1235
  await checkInactiveDefaultDecisionRecords(checks, reportRuntime);
1284
1236
  }
1285
1237
  await checkActiveChangeConsistency(checks);
1238
+ if (configValid)
1239
+ await checkArchitecture(checks);
1286
1240
  const result = {
1287
1241
  command: "doctor",
1288
1242
  ok: checks.every((check) => check.status !== "issue"),
@@ -1294,6 +1248,42 @@ async function runDoctor(options = {}) {
1294
1248
  };
1295
1249
  return result;
1296
1250
  }
1251
+ async function checkArchitecture(checks) {
1252
+ try {
1253
+ const architecture = await queryArchitecture();
1254
+ if (!architecture.configured) {
1255
+ checks.push({
1256
+ status: "info",
1257
+ code: "architecture_not_configured",
1258
+ label: ARCHITECTURE_FILE,
1259
+ message: "Optional architecture model is not configured."
1260
+ });
1261
+ } else if (architecture.diagnostics.length) {
1262
+ for (const diagnostic of architecture.diagnostics) {
1263
+ checks.push({
1264
+ status: "issue",
1265
+ code: `architecture_${diagnostic.code}`,
1266
+ label: `architecture binding: ${diagnostic.file ?? ARCHITECTURE_FILE}`,
1267
+ message: `${diagnostic.file ?? ARCHITECTURE_FILE}: ${diagnostic.message}`
1268
+ });
1269
+ }
1270
+ } else {
1271
+ checks.push({
1272
+ status: "ok",
1273
+ code: "architecture_valid",
1274
+ label: "architecture structure and document bindings",
1275
+ message: `${architecture.nodes.length} nodes, ${architecture.relations.length} relations, ${architecture.views.length} views. Structural and reference validity does not establish semantic agreement with implementation.`
1276
+ });
1277
+ }
1278
+ } catch (error) {
1279
+ checks.push({
1280
+ status: "issue",
1281
+ code: "architecture_inspection_failed",
1282
+ label: ARCHITECTURE_FILE,
1283
+ message: `${ARCHITECTURE_FILE}: ${toErrorMessage(error)}`
1284
+ });
1285
+ }
1286
+ }
1297
1287
  async function reportProjectRuntime(checks) {
1298
1288
  let sourceMode = false;
1299
1289
  try {
@@ -1389,7 +1379,7 @@ async function checkAgents(checks, reportRuntime) {
1389
1379
  }
1390
1380
  let agents;
1391
1381
  try {
1392
- agents = await readFile4("AGENTS.md", "utf-8");
1382
+ agents = await readFile3("AGENTS.md", "utf-8");
1393
1383
  } catch (error) {
1394
1384
  reportRuntime({
1395
1385
  code: "agents_read_failed",
@@ -1448,7 +1438,7 @@ async function checkSpecsTree(checks, reportRuntime) {
1448
1438
  }
1449
1439
  }
1450
1440
  async function checkArchiveNaming(checks) {
1451
- const archivesDir = join3(RSP_DIR, "archives");
1441
+ const archivesDir = join2(RSP_DIR, "archives");
1452
1442
  const inspection = await inspectArchiveTree({ archivesDir });
1453
1443
  if (inspection.diagnostics.length > 0) {
1454
1444
  checks.push({
@@ -1812,7 +1802,7 @@ function emptyCollectionSummary() {
1812
1802
  }
1813
1803
 
1814
1804
  // src/commands/ready.ts
1815
- import { readFile as readFile5 } from "fs/promises";
1805
+ import { readFile as readFile4 } from "fs/promises";
1816
1806
  function readyError(name, error, kind) {
1817
1807
  return { command: "ready", ok: false, change: name || null, path: null, warnings: [], runtime: [], error, kind };
1818
1808
  }
@@ -1832,7 +1822,7 @@ async function showReady(name) {
1832
1822
  const runtime = [];
1833
1823
  let content;
1834
1824
  try {
1835
- content = await readFile5(srcPath, "utf-8");
1825
+ content = await readFile4(srcPath, "utf-8");
1836
1826
  } catch {
1837
1827
  return readyError(name, { code: "change_read_failed", message: `unable to read .rsp/changes/${name}.md` }, "read");
1838
1828
  }
@@ -1876,7 +1866,7 @@ async function showReady(name) {
1876
1866
  }
1877
1867
 
1878
1868
  // src/commands/show.ts
1879
- import { readFile as readFile6 } from "fs/promises";
1869
+ import { readFile as readFile5 } from "fs/promises";
1880
1870
  function showError(error, runtime = []) {
1881
1871
  const nextActions = error.code === "no_focused_change" ? ["Run: rsp status", "Run: rsp focus <name>", "Or run: rsp create <name>"] : [];
1882
1872
  return { command: "show", ok: false, change: null, contextPaths: [], runtime, nextActions, error };
@@ -1920,7 +1910,7 @@ async function showChange(nameOrFocused, options = {}) {
1920
1910
  const srcPath = workRef.path;
1921
1911
  let content;
1922
1912
  try {
1923
- content = await readFile6(srcPath, "utf-8");
1913
+ content = await readFile5(srcPath, "utf-8");
1924
1914
  } catch {
1925
1915
  return showError({ code: "change_read_failed", message: `unable to read .rsp/changes/${name}.md` }, runtime);
1926
1916
  }
@@ -1949,7 +1939,7 @@ async function showChange(nameOrFocused, options = {}) {
1949
1939
  const markerPath = focusMarkers.get(name);
1950
1940
  let markerContent;
1951
1941
  try {
1952
- markerContent = await readFile6(markerPath);
1942
+ markerContent = await readFile5(markerPath);
1953
1943
  } catch (error) {
1954
1944
  reportRuntime({
1955
1945
  code: "focus_marker_read_failed",
@@ -2850,7 +2840,7 @@ function formatArchiveReady(value) {
2850
2840
  }
2851
2841
 
2852
2842
  // src/cli/commands/inspection.ts
2853
- var configCommand = defineCommand({
2843
+ var configCommand = defineCommand2({
2854
2844
  meta: {
2855
2845
  name: "config",
2856
2846
  description: "Inspect effective project configuration without scanning work state"
@@ -2866,7 +2856,7 @@ var configCommand = defineCommand({
2866
2856
  }, args);
2867
2857
  }
2868
2858
  });
2869
- var specsCommand = defineCommand({
2859
+ var specsCommand = defineCommand2({
2870
2860
  meta: {
2871
2861
  name: "specs",
2872
2862
  description: "Inspect current Specs and Decision Records or run bounded literal search"
@@ -2905,7 +2895,7 @@ var specsCommand = defineCommand({
2905
2895
  }, args);
2906
2896
  }
2907
2897
  });
2908
- var statusCommand = defineCommand({
2898
+ var statusCommand = defineCommand2({
2909
2899
  meta: {
2910
2900
  name: "status",
2911
2901
  description: "Show project status summary with current focus information"
@@ -2953,7 +2943,7 @@ var statusCommand = defineCommand({
2953
2943
  }, args);
2954
2944
  }
2955
2945
  });
2956
- var checkCommand = defineCommand({
2946
+ var checkCommand = defineCommand2({
2957
2947
  meta: {
2958
2948
  name: "check",
2959
2949
  description: "Validate changes (frontmatter, sections, template text, deltas, scenarios)"
@@ -2979,7 +2969,7 @@ var checkCommand = defineCommand({
2979
2969
  }, args);
2980
2970
  }
2981
2971
  });
2982
- var doctorCommand = defineCommand({
2972
+ var doctorCommand = defineCommand2({
2983
2973
  meta: {
2984
2974
  name: "doctor",
2985
2975
  description: "Check RSP setup health and common integration issues"
@@ -3007,7 +2997,7 @@ var doctorCommand = defineCommand({
3007
2997
  }, args);
3008
2998
  }
3009
2999
  });
3010
- var readyCommand = defineCommand({
3000
+ var readyCommand = defineCommand2({
3011
3001
  meta: {
3012
3002
  name: "ready",
3013
3003
  description: "Preview archive readiness for a change without moving it"
@@ -3033,7 +3023,7 @@ var readyCommand = defineCommand({
3033
3023
  }, args);
3034
3024
  }
3035
3025
  });
3036
- var showCommand = defineCommand({
3026
+ var showCommand = defineCommand2({
3037
3027
  meta: {
3038
3028
  name: "show",
3039
3029
  description: "Show change context with readiness signals and relevant paths"
@@ -3064,7 +3054,7 @@ var showCommand = defineCommand({
3064
3054
  }, args);
3065
3055
  }
3066
3056
  });
3067
- var historyCommand = defineCommand({
3057
+ var historyCommand = defineCommand2({
3068
3058
  meta: {
3069
3059
  name: "history",
3070
3060
  description: "Query bounded archived Change summaries or one exact archived WorkRef"
@@ -3130,14 +3120,14 @@ var inspectionCommands = {
3130
3120
  };
3131
3121
 
3132
3122
  // src/cli/commands/setup.ts
3133
- import { defineCommand as defineCommand2 } from "citty";
3123
+ import { defineCommand as defineCommand3 } from "citty";
3134
3124
 
3135
3125
  // src/commands/add-spec.ts
3136
3126
  import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
3137
- import { join as join4 } from "path";
3127
+ import { join as join3 } from "path";
3138
3128
 
3139
3129
  // src/core/lock.ts
3140
- import { mkdir as mkdir2, readFile as readFile7, unlink, writeFile } from "fs/promises";
3130
+ import { mkdir as mkdir2, readFile as readFile6, unlink, writeFile } from "fs/promises";
3141
3131
  async function withRspLock(operation, fn) {
3142
3132
  requireManagedDirectory(RSP_DIR, "RSP root", { allowMissing: true });
3143
3133
  await mkdir2(RSP_DIR, { recursive: true });
@@ -3162,7 +3152,7 @@ ${(/* @__PURE__ */ new Date()).toISOString()}`, { flag: "wx" });
3162
3152
  }
3163
3153
  async function handleStaleLock(operation) {
3164
3154
  try {
3165
- const content = await readFile7(LOCK_PATH, "utf-8");
3155
+ const content = await readFile6(LOCK_PATH, "utf-8");
3166
3156
  const lines = content.trim().split("\n");
3167
3157
  const pid = Number(lines[0]);
3168
3158
  if (pid && Number.isFinite(pid)) {
@@ -3220,10 +3210,10 @@ async function addSpec(name, projectName = "project") {
3220
3210
  return { ok: false, message: `.rsp/config.yaml could not be parsed: ${toErrorMessage(error)}` };
3221
3211
  }
3222
3212
  return withRspLock("add-spec", async () => {
3223
- const specsDir = join4(RSP_DIR, "specs");
3213
+ const specsDir = join3(RSP_DIR, "specs");
3224
3214
  const segments = name.split("/");
3225
3215
  const parent = resolveManagedDirectoryChain(specsDir, segments.slice(0, -1), "spec path");
3226
- const path = join4(parent, `${segments.at(-1)}.md`);
3216
+ const path = join3(parent, `${segments.at(-1)}.md`);
3227
3217
  const inspection = await inspectManagedFileTree(specsDir, "Specs");
3228
3218
  if (inspection.issues.length > 0)
3229
3219
  throw inspection.issues[0];
@@ -3243,30 +3233,30 @@ async function addSpec(name, projectName = "project") {
3243
3233
 
3244
3234
  // src/commands/init.ts
3245
3235
  import { existsSync as existsSync2 } from "fs";
3246
- import { mkdir as mkdir4, readdir as readdir3, readFile as readFile9 } from "fs/promises";
3247
- import { join as join6 } from "path";
3236
+ import { mkdir as mkdir4, readdir as readdir3, readFile as readFile8 } from "fs/promises";
3237
+ import { join as join5 } from "path";
3248
3238
 
3249
3239
  // src/core/setup-files.ts
3250
3240
  import { constants } from "fs";
3251
- import { access, chmod as chmod2, link, mkdtemp as mkdtemp2, readFile as readFile8, rename as rename2, rm as rm2, stat as stat2, writeFile as writeFile3 } from "fs/promises";
3252
- import { dirname as dirname2, join as join5 } from "path";
3241
+ import { access, chmod as chmod2, link, mkdtemp as mkdtemp2, readFile as readFile7, rename as rename2, rm as rm2, stat as stat2, writeFile as writeFile3 } from "fs/promises";
3242
+ import { dirname as dirname2, join as join4 } from "path";
3253
3243
  async function updateSetupFile(path, render) {
3254
3244
  const exists = requireManagedFile(path, "setup file", { allowMissing: true });
3255
- const current = exists ? await readFile8(path, "utf8") : null;
3245
+ const current = exists ? await readFile7(path, "utf8") : null;
3256
3246
  const next = render(current);
3257
3247
  if (next === current)
3258
3248
  return false;
3259
3249
  if (exists)
3260
3250
  await access(path, constants.W_OK);
3261
- const temporary = await mkdtemp2(join5(dirname2(path), ".rsp-write-"));
3262
- const prepared = join5(temporary, "next");
3251
+ const temporary = await mkdtemp2(join4(dirname2(path), ".rsp-write-"));
3252
+ const prepared = join4(temporary, "next");
3263
3253
  let failure2;
3264
3254
  try {
3265
3255
  await writeFile3(prepared, next, { flag: "wx" });
3266
3256
  if (exists)
3267
3257
  await chmod2(prepared, (await stat2(path)).mode & 511);
3268
3258
  const stillExists = requireManagedFile(path, "setup file", { allowMissing: true });
3269
- if (stillExists !== exists || stillExists && await readFile8(path, "utf8") !== current)
3259
+ if (stillExists !== exists || stillExists && await readFile7(path, "utf8") !== current)
3270
3260
  throw new Error(`Setup file changed during update: ${path}`);
3271
3261
  if (exists)
3272
3262
  await rename2(prepared, path);
@@ -3307,7 +3297,7 @@ async function initProject(args = {}) {
3307
3297
  const pathIssue = await validateDecisionRecordsFilesystemPath(decisionRecordsPath);
3308
3298
  if (pathIssue)
3309
3299
  throw new Error(pathIssue);
3310
- const dirs = [join6(RSP_DIR, "specs"), CHANGES_DIR, FOCUS_DIR, join6(RSP_DIR, "archives"), decisionRecordsPath];
3300
+ const dirs = [join5(RSP_DIR, "specs"), CHANGES_DIR, FOCUS_DIR, join5(RSP_DIR, "archives"), decisionRecordsPath];
3311
3301
  for (const path of dirs)
3312
3302
  resolveManagedDirectoryChain(process.cwd(), path.split("/"), "project directory");
3313
3303
  const completed = [];
@@ -3327,12 +3317,12 @@ async function initProject(args = {}) {
3327
3317
  }
3328
3318
  await ensureFile(CONFIG_PATH, generateConfigTemplate());
3329
3319
  clearConfigCache();
3330
- await ensureFile(join6(RSP_DIR, "specs/design.md"), generateDesignContent(projectName));
3320
+ await ensureFile(join5(RSP_DIR, "specs/design.md"), generateDesignContent(projectName));
3331
3321
  if ((await readdir3(decisionRecordsPath)).length === 0)
3332
- await ensureFile(join6(decisionRecordsPath, ".gitkeep"), "");
3333
- await ensureFile(join6(CHANGES_DIR, ".gitkeep"), "");
3334
- await ensureFile(join6(FOCUS_DIR, ".gitkeep"), "");
3335
- await ensureFile(join6(RSP_DIR, ".gitignore"), "# Transient files that should not be committed\n.lock\n");
3322
+ await ensureFile(join5(decisionRecordsPath, ".gitkeep"), "");
3323
+ await ensureFile(join5(CHANGES_DIR, ".gitkeep"), "");
3324
+ await ensureFile(join5(FOCUS_DIR, ".gitkeep"), "");
3325
+ await ensureFile(join5(RSP_DIR, ".gitignore"), "# Transient files that should not be committed\n.lock\n");
3336
3326
  if (args.withProjectSetup) {
3337
3327
  const work = resolveWorkRef("project-setup", { executable: true });
3338
3328
  await ensureFile(work.path, generateChangeContent("project-setup"));
@@ -3347,7 +3337,7 @@ async function initProject(args = {}) {
3347
3337
  if (runtime.mode === "package" && await updateSetupFile(PROJECT_VERSION_PATH, () => `${version}
3348
3338
  `))
3349
3339
  completed.push(`pinned ${version}`);
3350
- return { ok: true, isNew, created: completed.length > 0, decisionRecordsPath, withProjectSetup: Boolean(args.withProjectSetup), agentsUpdated, skills, managedAgents: mode === "print" ? await readFile9("AGENTS.md", "utf8") : void 0 };
3340
+ return { ok: true, isNew, created: completed.length > 0, decisionRecordsPath, withProjectSetup: Boolean(args.withProjectSetup), agentsUpdated, skills, managedAgents: mode === "print" ? await readFile8("AGENTS.md", "utf8") : void 0 };
3351
3341
  } catch (error) {
3352
3342
  throw new Error(`Init stopped; completed: ${completed.join(", ") || "none"}. No rollback was attempted. Fix the cause and rerun init with the same target CLI. ${error instanceof Error ? error.message : String(error)}`, { cause: error });
3353
3343
  }
@@ -3356,17 +3346,17 @@ async function initProject(args = {}) {
3356
3346
 
3357
3347
  // src/commands/update.ts
3358
3348
  import { existsSync as existsSync3 } from "fs";
3359
- import { readFile as readFile12, unlink as unlink3 } from "fs/promises";
3360
- import { join as join8 } from "path";
3349
+ import { readFile as readFile11, unlink as unlink3 } from "fs/promises";
3350
+ import { join as join7 } from "path";
3361
3351
 
3362
3352
  // src/commands/archive-index-migration.ts
3363
- import { readFile as readFile10 } from "fs/promises";
3364
- import { join as join7 } from "path";
3353
+ import { readFile as readFile9 } from "fs/promises";
3354
+ import { join as join6 } from "path";
3365
3355
  async function isLegacyArchiveIndex() {
3366
- const path = join7(ARCHIVES_DIR, "INDEX.md");
3356
+ const path = join6(ARCHIVES_DIR, "INDEX.md");
3367
3357
  if (!requireManagedFile(path, "legacy archive index", { allowMissing: true }))
3368
3358
  return false;
3369
- return isLegacyArchiveIndexContent(await readFile10(path, "utf-8"));
3359
+ return isLegacyArchiveIndexContent(await readFile9(path, "utf-8"));
3370
3360
  }
3371
3361
  function isLegacyArchiveIndexContent(content) {
3372
3362
  try {
@@ -3378,7 +3368,7 @@ function isLegacyArchiveIndexContent(content) {
3378
3368
  }
3379
3369
 
3380
3370
  // src/commands/specs-index-migration.ts
3381
- import { readFile as readFile11, unlink as unlink2 } from "fs/promises";
3371
+ import { readFile as readFile10, unlink as unlink2 } from "fs/promises";
3382
3372
  import { dirname as dirname3, resolve } from "path";
3383
3373
  async function inspectGeneratedSpecsIndexMigration(cwd = process.cwd()) {
3384
3374
  const inspection = await inspectSpecs({ cwd, allowMissingDecisionRecords: true });
@@ -3393,7 +3383,7 @@ async function removeGeneratedSpecsIndex(path) {
3393
3383
  resolveManagedDirectoryChain(process.cwd(), dirname3(path).split("/"), "Specs parent");
3394
3384
  if (!requireManagedFile(path, "generated Specs index", { allowMissing: true }))
3395
3385
  return false;
3396
- if (!isRecognizedGeneratedSpecsIndex(await readFile11(resolve(path), "utf8"), path))
3386
+ if (!isRecognizedGeneratedSpecsIndex(await readFile10(resolve(path), "utf8"), path))
3397
3387
  throw new Error(`Specs index is no longer generated; left untouched: ${path}`);
3398
3388
  await unlink2(path);
3399
3389
  return true;
@@ -3418,12 +3408,12 @@ async function updateProject(options = {}) {
3418
3408
  return { ok: false, actions: [], updated: false, events: [{ type: "migration-diagnostics", diagnostics: rules.diagnostics }], migration };
3419
3409
  requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true });
3420
3410
  resolveManagedDirectoryChain(process.cwd(), [RSP_DIR, "archives"], "archive parent");
3421
- requireManagedFile(join8(RSP_DIR, "archives/INDEX.md"), "archive index", { allowMissing: true });
3411
+ requireManagedFile(join7(RSP_DIR, "archives/INDEX.md"), "archive index", { allowMissing: true });
3422
3412
  const plan = await inspectGeneratedSpecsIndexMigration();
3423
3413
  if (!plan.inspectionComplete || plan.ownerControlled.length)
3424
3414
  throw new Error(`Generated Specs-index migration requires owner review before update: ${[...plan.ownerControlled, ...plan.diagnostics].join("; ")}`);
3425
3415
  const projectName = await detectProjectName();
3426
- const agents = requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true }) ? await readFile12("AGENTS.md", "utf8") : null;
3416
+ const agents = requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true }) ? await readFile11("AGENTS.md", "utf8") : null;
3427
3417
  const refreshAgents = (current) => upsertRspAgentsBlock(current ?? `# ${projectName}
3428
3418
 
3429
3419
  `, runtime).content;
@@ -3464,7 +3454,7 @@ async function updateProject(options = {}) {
3464
3454
  record(`generated Specs index removed: ${path}`);
3465
3455
  }
3466
3456
  if (await isLegacyArchiveIndex()) {
3467
- await unlink3(join8(RSP_DIR, "archives/INDEX.md"));
3457
+ await unlink3(join7(RSP_DIR, "archives/INDEX.md"));
3468
3458
  record("legacy Archive Index removed");
3469
3459
  }
3470
3460
  if (await updateSetupFile("AGENTS.md", refreshAgents))
@@ -3578,7 +3568,7 @@ function presentUpdate(result, dryRun = false) {
3578
3568
  }
3579
3569
 
3580
3570
  // src/cli/commands/setup.ts
3581
- var initCommand = defineCommand2({
3571
+ var initCommand = defineCommand3({
3582
3572
  meta: {
3583
3573
  name: "init",
3584
3574
  description: "Scaffold .rsp/ and ensure AGENTS.md contains the RSP entry block"
@@ -3606,7 +3596,7 @@ var initCommand = defineCommand2({
3606
3596
  }, args);
3607
3597
  }
3608
3598
  });
3609
- var addSpecCommand = defineCommand2({
3599
+ var addSpecCommand = defineCommand3({
3610
3600
  meta: {
3611
3601
  name: "spec",
3612
3602
  description: "Create .rsp/specs/<name>.md for direct Specs queries"
@@ -3626,7 +3616,7 @@ var addSpecCommand = defineCommand2({
3626
3616
  }, args);
3627
3617
  }
3628
3618
  });
3629
- var addCommand = defineCommand2({
3619
+ var addCommand = defineCommand3({
3630
3620
  meta: {
3631
3621
  name: "add",
3632
3622
  description: "Add an optional durable spec file"
@@ -3635,7 +3625,7 @@ var addCommand = defineCommand2({
3635
3625
  spec: addSpecCommand
3636
3626
  }
3637
3627
  });
3638
- var updateCommand = defineCommand2({
3628
+ var updateCommand = defineCommand3({
3639
3629
  meta: {
3640
3630
  name: "update",
3641
3631
  description: "Update the complete pinned environment and remove retired managed assets"
@@ -3660,7 +3650,7 @@ var setupCommands = {
3660
3650
  };
3661
3651
 
3662
3652
  // src/cli/commands/skills.ts
3663
- import { defineCommand as defineCommand3 } from "citty";
3653
+ import { defineCommand as defineCommand4 } from "citty";
3664
3654
 
3665
3655
  // src/cli/presenters/skills.ts
3666
3656
  function presentPackagedSkillInventory(inventory, json = false) {
@@ -3678,7 +3668,7 @@ function presentPackagedSkillInventory(inventory, json = false) {
3678
3668
  }
3679
3669
 
3680
3670
  // src/cli/commands/skills.ts
3681
- var skillsListCommand = defineCommand3({
3671
+ var skillsListCommand = defineCommand4({
3682
3672
  meta: { name: "list", description: "Inspect the complete package-owned Skill inventory" },
3683
3673
  args: { ...jsonArgs },
3684
3674
  async run({ args }) {
@@ -3689,19 +3679,19 @@ var skillsListCommand = defineCommand3({
3689
3679
  }
3690
3680
  });
3691
3681
  var skillsCommands = {
3692
- skills: defineCommand3({
3682
+ skills: defineCommand4({
3693
3683
  meta: { name: "skills", description: "Inspect Skills; use init or update to manage the complete environment" },
3694
3684
  subCommands: { list: skillsListCommand }
3695
3685
  })
3696
3686
  };
3697
3687
 
3698
3688
  // src/cli/commands/work.ts
3699
- import { defineCommand as defineCommand4 } from "citty";
3689
+ import { defineCommand as defineCommand5 } from "citty";
3700
3690
 
3701
3691
  // src/commands/archive.ts
3702
3692
  import { existsSync as existsSync4, readdirSync } from "fs";
3703
- import { mkdir as mkdir5, readFile as readFile13, rename as rename3, unlink as unlink4 } from "fs/promises";
3704
- import { basename as basename2, join as join9 } from "path";
3693
+ import { mkdir as mkdir5, readFile as readFile12, rename as rename3, unlink as unlink4 } from "fs/promises";
3694
+ import { basename as basename2, join as join8 } from "path";
3705
3695
  async function archiveChange(name) {
3706
3696
  if (!name) {
3707
3697
  return { ok: false, kind: "usage", message: "rsp archive <name>" };
@@ -3718,7 +3708,7 @@ async function archiveChange(name) {
3718
3708
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3719
3709
  const base = basename2(workRef.name);
3720
3710
  const archiveName = resolveArchiveName(archiveSubdir, date, base);
3721
- const content = await readFile13(srcPath, "utf-8");
3711
+ const content = await readFile12(srcPath, "utf-8");
3722
3712
  const configInspection = await inspectRspConfig();
3723
3713
  if (configInspection.issues.length > 0) {
3724
3714
  return {
@@ -3747,7 +3737,7 @@ async function archiveChange(name) {
3747
3737
  };
3748
3738
  }
3749
3739
  await mkdir5(archiveSubdir, { recursive: true });
3750
- await rename3(srcPath, join9(archiveSubdir, archiveName));
3740
+ await rename3(srcPath, join8(archiveSubdir, archiveName));
3751
3741
  const postArchiveWarnings = [];
3752
3742
  let focusCleared = false;
3753
3743
  if (existsSync4(focusEntry)) {
@@ -3862,11 +3852,11 @@ async function createChange(name, summary = "", kind, options = {}) {
3862
3852
  }
3863
3853
 
3864
3854
  // src/commands/focus.ts
3865
- import { Buffer as Buffer2 } from "buffer";
3855
+ import { Buffer } from "buffer";
3866
3856
  import { randomUUID } from "crypto";
3867
3857
  import { existsSync as existsSync6 } from "fs";
3868
3858
  import { mkdir as mkdir7, open, rename as rename4, unlink as unlink6 } from "fs/promises";
3869
- import { basename as basename3, dirname as dirname5, join as join10 } from "path";
3859
+ import { basename as basename3, dirname as dirname5, join as join9 } from "path";
3870
3860
  async function focusChange(name, options = {}) {
3871
3861
  if (!name) {
3872
3862
  return { ok: false, kind: "usage", message: "rsp focus <name>" };
@@ -3901,7 +3891,7 @@ async function readCapsule(source) {
3901
3891
  }
3902
3892
  async function replaceFocusCapsule(path, content) {
3903
3893
  requireManagedFile(path, "focus marker", { allowMissing: true });
3904
- const temporaryPath = join10(dirname5(path), `.${basename3(path)}.${randomUUID()}.tmp`);
3894
+ const temporaryPath = join9(dirname5(path), `.${basename3(path)}.${randomUUID()}.tmp`);
3905
3895
  let handle;
3906
3896
  try {
3907
3897
  handle = await open(temporaryPath, "wx");
@@ -3934,13 +3924,13 @@ async function readBoundedStdin() {
3934
3924
  const chunks = [];
3935
3925
  let size = 0;
3936
3926
  for await (const chunk of process.stdin) {
3937
- const buffer = Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk);
3927
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
3938
3928
  size += buffer.byteLength;
3939
3929
  if (size > MAX_FOCUS_CAPSULE_BYTES)
3940
3930
  throw new Error(`focus capsule exceeds ${MAX_FOCUS_CAPSULE_BYTES} UTF-8 bytes`);
3941
3931
  chunks.push(buffer);
3942
3932
  }
3943
- return Buffer2.concat(chunks, size);
3933
+ return Buffer.concat(chunks, size);
3944
3934
  }
3945
3935
  async function unfocusChange(name) {
3946
3936
  if (!name) {
@@ -3975,8 +3965,8 @@ function workRefFailure(error) {
3975
3965
  // src/commands/group.ts
3976
3966
  import { randomUUID as randomUUID2 } from "crypto";
3977
3967
  import { existsSync as existsSync7 } from "fs";
3978
- import { link as link2, mkdir as mkdir8, readdir as readdir4, readFile as readFile14, rename as rename5, unlink as unlink7, writeFile as writeFile5 } from "fs/promises";
3979
- import { join as join11 } from "path";
3968
+ import { link as link2, mkdir as mkdir8, readdir as readdir4, readFile as readFile13, rename as rename5, unlink as unlink7, writeFile as writeFile5 } from "fs/promises";
3969
+ import { join as join10 } from "path";
3980
3970
  var ChangeGroupError = class extends Error {
3981
3971
  name = "ChangeGroupError";
3982
3972
  };
@@ -4037,14 +4027,14 @@ async function closeChangeGroup(name) {
4037
4027
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4038
4028
  const archiveName = resolveArchiveName(archiveDirectory, date, "brief");
4039
4029
  await mkdir8(archiveDirectory, { recursive: true });
4040
- await rename5(ref.path, join11(archiveDirectory, archiveName));
4030
+ await rename5(ref.path, join10(archiveDirectory, archiveName));
4041
4031
  const warnings = [];
4042
4032
  try {
4043
4033
  await cleanupEmptyParentDirs(ref.path, CHANGES_DIR);
4044
4034
  } catch (error) {
4045
4035
  warnings.push(`changes directory cleanup failed: ${toErrorMessage(error)}`);
4046
4036
  }
4047
- return { ok: true, action: "close", groupName, archivePath: join11(archiveDirectory, archiveName), warnings };
4037
+ return { ok: true, action: "close", groupName, archivePath: join10(archiveDirectory, archiveName), warnings };
4048
4038
  });
4049
4039
  } catch (error) {
4050
4040
  if (error instanceof WorkRefError || error instanceof ChangeGroupError) {
@@ -4068,8 +4058,8 @@ async function reopenChangeGroup(name, options) {
4068
4058
  return await withRspLock("reopen-change-group", async () => {
4069
4059
  const warnings = [];
4070
4060
  const groupName = normalizeWorkRefSegment(name);
4071
- await requireEmptyGroupRecoverySubtree(join11(CHANGES_DIR, groupName), `Change Group work subtree for ${groupName}`);
4072
- await requireEmptyGroupRecoverySubtree(join11(FOCUS_DIR, groupName), `Change Group focus subtree for ${groupName}`);
4061
+ await requireEmptyGroupRecoverySubtree(join10(CHANGES_DIR, groupName), `Change Group work subtree for ${groupName}`);
4062
+ await requireEmptyGroupRecoverySubtree(join10(FOCUS_DIR, groupName), `Change Group focus subtree for ${groupName}`);
4073
4063
  const ref = resolveWorkRef(`${groupName}/brief`);
4074
4064
  if (ref.kind !== "group-brief")
4075
4065
  throw new ChangeGroupError(`invalid Change Group name: ${name}`);
@@ -4092,13 +4082,13 @@ async function reopenChangeGroup(name, options) {
4092
4082
  }
4093
4083
  if (existsSync7(ref.path))
4094
4084
  throw new ArchiveHistoryError("open_group_exists", `open Change Group already exists: ${groupName}`);
4095
- const archivedContent = await readFile14(record.sourcePath, "utf-8");
4085
+ const archivedContent = await readFile13(record.sourcePath, "utf-8");
4096
4086
  const document = parseRspDocument(archivedContent, GROUP_BRIEF_DOCUMENT_SCHEMA);
4097
4087
  validateArchivedGroupBrief(document, groupName);
4098
4088
  const evidenceKey = `${GROUP_REOPEN_COMPLETION_PREFIX} \`${record.path}\`: ${reason}`;
4099
4089
  const retainedEvidence = /* @__PURE__ */ new Set();
4100
4090
  for (const retained of inspection.groupBriefs.filter((candidate) => candidate.group === groupName)) {
4101
- const retainedDocument = retained.sourcePath === record.sourcePath ? document : parseRspDocument(await readFile14(retained.sourcePath, "utf-8"), GROUP_BRIEF_DOCUMENT_SCHEMA);
4091
+ const retainedDocument = retained.sourcePath === record.sourcePath ? document : parseRspDocument(await readFile13(retained.sourcePath, "utf-8"), GROUP_BRIEF_DOCUMENT_SCHEMA);
4102
4092
  for (const item of getGroupReopenEvidence(retainedDocument))
4103
4093
  retainedEvidence.add(item.key);
4104
4094
  }
@@ -4115,7 +4105,7 @@ async function reopenChangeGroup(name, options) {
4115
4105
  );
4116
4106
  const groupDirectory = resolveManagedDirectoryChain(CHANGES_DIR, [groupName], "Change Group path");
4117
4107
  await mkdir8(groupDirectory, { recursive: true });
4118
- const temporaryPath = join11(RSP_DIR, `.group-reopen-${process.pid}-${randomUUID2()}.tmp`);
4108
+ const temporaryPath = join10(RSP_DIR, `.group-reopen-${process.pid}-${randomUUID2()}.tmp`);
4119
4109
  let mutationError;
4120
4110
  try {
4121
4111
  await writeFile5(temporaryPath, reopenedContent, { flag: "wx" });
@@ -4200,7 +4190,7 @@ function collectCloseReasons(group, errors) {
4200
4190
 
4201
4191
  // src/commands/reopen.ts
4202
4192
  import { existsSync as existsSync8 } from "fs";
4203
- import { mkdir as mkdir9, readFile as readFile15, unlink as unlink8, writeFile as writeFile6 } from "fs/promises";
4193
+ import { mkdir as mkdir9, readFile as readFile14, unlink as unlink8, writeFile as writeFile6 } from "fs/promises";
4204
4194
  import { dirname as dirname6 } from "path";
4205
4195
  async function reopenChange(name, options) {
4206
4196
  if (!name) {
@@ -4250,7 +4240,7 @@ async function reopenChange(name, options) {
4250
4240
  const focusEntry = resolveFocusMarkerPath(workRef);
4251
4241
  if (existsSync8(focusEntry))
4252
4242
  throw new ArchiveHistoryError("focus_marker_exists", `focus marker already exists for non-open Change: ${name}; run rsp doctor`);
4253
- const archivedContent = await readFile15(record.sourcePath, "utf-8");
4243
+ const archivedContent = await readFile14(record.sourcePath, "utf-8");
4254
4244
  const reopenedContent = appendChecklistItem(
4255
4245
  appendChecklistItem(archivedContent, "tasks", `- [ ] Resolve reopened concern: ${reason}`),
4256
4246
  "verify",
@@ -4420,7 +4410,7 @@ function presentReopen(result) {
4420
4410
 
4421
4411
  // src/cli/commands/work.ts
4422
4412
  function createCreateCommand(deprecatedLite) {
4423
- return defineCommand4({
4413
+ return defineCommand5({
4424
4414
  meta: {
4425
4415
  name: "create",
4426
4416
  description: "Create .rsp/changes/<name>.md [summary]"
@@ -4445,7 +4435,7 @@ function createCreateCommand(deprecatedLite) {
4445
4435
  }
4446
4436
  },
4447
4437
  async run({ args }) {
4448
- const summary = Array.isArray(args._) && args._.length > 1 ? args._.slice(1).join(" ") : "";
4438
+ const summary = args._.slice(1).join(" ");
4449
4439
  await executeCliCommand({
4450
4440
  execute: () => createChange(args.name, summary, args.kind, {
4451
4441
  issue: args.issue,
@@ -4458,7 +4448,7 @@ function createCreateCommand(deprecatedLite) {
4458
4448
  }
4459
4449
  });
4460
4450
  }
4461
- var groupCreateCommand = defineCommand4({
4451
+ var groupCreateCommand = defineCommand5({
4462
4452
  meta: {
4463
4453
  name: "create",
4464
4454
  description: "Create an unfocused .rsp/changes/<group>/00-brief.md"
@@ -4471,18 +4461,18 @@ var groupCreateCommand = defineCommand4({
4471
4461
  }
4472
4462
  },
4473
4463
  async run({ args }) {
4474
- const goal = Array.isArray(args._) && args._.length > 1 ? args._.slice(1).join(" ") : "";
4464
+ const goal = args._.slice(1).join(" ");
4475
4465
  await executeCliCommand({ execute: () => createChangeGroup(args.name, goal), present: presentGroup, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4476
4466
  }
4477
4467
  });
4478
- var groupCommand = defineCommand4({
4468
+ var groupCommand = defineCommand5({
4479
4469
  meta: {
4480
4470
  name: "group",
4481
4471
  description: "Create, close, and explicitly reopen shallow Change Groups"
4482
4472
  },
4483
4473
  subCommands: {
4484
4474
  create: groupCreateCommand,
4485
- close: defineCommand4({
4475
+ close: defineCommand5({
4486
4476
  meta: {
4487
4477
  name: "close",
4488
4478
  description: "Archive a completed Group Brief after all child Changes are archived"
@@ -4498,7 +4488,7 @@ var groupCommand = defineCommand4({
4498
4488
  await executeCliCommand({ execute: () => closeChangeGroup(args.name), present: presentGroup, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4499
4489
  }
4500
4490
  }),
4501
- reopen: defineCommand4({
4491
+ reopen: defineCommand5({
4502
4492
  meta: {
4503
4493
  name: "reopen",
4504
4494
  description: "Restore one archived Group Brief while retaining history"
@@ -4525,7 +4515,7 @@ var groupCommand = defineCommand4({
4525
4515
  })
4526
4516
  }
4527
4517
  });
4528
- var archiveCommand = defineCommand4({
4518
+ var archiveCommand = defineCommand5({
4529
4519
  meta: {
4530
4520
  name: "archive",
4531
4521
  description: "Archive an open change into .rsp/archives/"
@@ -4549,7 +4539,7 @@ var archiveCommand = defineCommand4({
4549
4539
  await executeCliCommand({ execute: () => archiveChange(args.name), present: presentArchive, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4550
4540
  }
4551
4541
  });
4552
- var reopenCommand = defineCommand4({
4542
+ var reopenCommand = defineCommand5({
4553
4543
  meta: {
4554
4544
  name: "reopen",
4555
4545
  description: "Restore one archived Change as focused open work while retaining history"
@@ -4574,7 +4564,7 @@ var reopenCommand = defineCommand4({
4574
4564
  await executeCliCommand({ execute: () => reopenChange(args.name, { from: args.from, reason: args.reason }), present: presentReopen, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4575
4565
  }
4576
4566
  });
4577
- var focusCommand = defineCommand4({
4567
+ var focusCommand = defineCommand5({
4578
4568
  meta: {
4579
4569
  name: "focus",
4580
4570
  description: "Mark an existing change as currently focused in .rsp/focus.d/"
@@ -4594,7 +4584,7 @@ var focusCommand = defineCommand4({
4594
4584
  await executeCliCommand({ execute: () => focusChange(args.name, { capsuleFile: args["capsule-file"] }), present: presentFocus, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4595
4585
  }
4596
4586
  });
4597
- var unfocusCommand = defineCommand4({
4587
+ var unfocusCommand = defineCommand5({
4598
4588
  meta: {
4599
4589
  name: "unfocus",
4600
4590
  description: "Remove a change from the current focus set in .rsp/focus.d/"
@@ -4624,13 +4614,15 @@ function createWorkCommands(deprecatedLite) {
4624
4614
  // src/cli/registry.ts
4625
4615
  function createRootCommand(options) {
4626
4616
  const workCommands = createWorkCommands(options.deprecatedLite);
4627
- return defineCommand5({
4617
+ return defineCommand6({
4628
4618
  meta: {
4629
4619
  name: "rsp",
4630
4620
  version: options.version,
4631
4621
  description: "RSP (Reliable Software Practice), a repository-native engineering workflow for humans and AI agents"
4632
4622
  },
4633
4623
  subCommands: {
4624
+ architecture: architectureCommand,
4625
+ view: viewCommand,
4634
4626
  init: setupCommands.init,
4635
4627
  add: setupCommands.add,
4636
4628
  specs: inspectionCommands.specs,
@@ -4715,7 +4707,7 @@ async function runCli(rawArgs = process.argv.slice(2)) {
4715
4707
  } else {
4716
4708
  const { resolveUiLocale } = await import("./locale-HT44UIUP.mjs");
4717
4709
  const locale = resolveUiLocale(lang, process.env.RSP_UI_LANG, process.env.LC_ALL ?? process.env.LC_MESSAGES ?? process.env.LANG ?? new Intl.DateTimeFormat().resolvedOptions().locale);
4718
- const { runTui } = await import("./entry-RIJQ2X46.mjs");
4710
+ const { runTui } = await import("./entry-NDASTAI5.mjs");
4719
4711
  const exitCode = await runTui(locale);
4720
4712
  if (exitCode !== 0)
4721
4713
  process.exitCode = exitCode;