@oevery/rsp 4.0.0 → 4.1.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.
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-JO6NDJM4.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,49 @@ 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.description}`);
193
+ for (const view of result.views) console.log(`View ${view.id}: ${view.title} (owner: ${view.node}; include: ${view.include.join(", ")})`);
194
+ for (const diagnostic of result.diagnostics) console.log(`${diagnostic.code}: ${diagnostic.message}`);
195
+ if (result.configured)
196
+ console.log(`Source: ${result.source.file} @ ${result.source.revision}`);
197
+ }
198
+ }
199
+ });
200
+ var viewCommand = defineCommand({
201
+ meta: { name: "view", description: "Open the shared local architecture viewer, inspect or stop its service" },
202
+ 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)" } },
203
+ async run({ args }) {
204
+ const unknown = Object.keys(args).filter((key) => !["action", "open", "_"].includes(key));
205
+ if (unknown.length || args._.length > 1 || args.action && !args.open)
206
+ throw new Error("rsp view accepts only an optional status/stop action or --no-open");
207
+ const { runView } = await import("./client-EHRWH5Q7.mjs");
208
+ await runView(args.action, args.open);
209
+ }
210
+ });
211
+
212
+ // src/cli/commands/inspection.ts
213
+ import { defineCommand as defineCommand2 } from "citty";
157
214
 
158
215
  // src/commands/check.ts
159
216
  import { readFile } from "fs/promises";
@@ -255,7 +312,6 @@ function inspectChangeDocument(content, options) {
255
312
  }
256
313
 
257
314
  // src/core/focus-capsule.ts
258
- import { Buffer } from "buffer";
259
315
  import { TextDecoder } from "util";
260
316
  var FOCUS_CAPSULE_VERSION = "<!-- rsp-focus:v1 -->";
261
317
  var LEGACY_WARNING = "legacy focus capsule has no structured recovery projection";
@@ -273,15 +329,6 @@ function inspectFocusCapsuleBytes(bytes) {
273
329
  } catch {
274
330
  return { kind: "invalid", code: "focus_capsule_invalid_utf8", message: "focus capsule must contain valid UTF-8" };
275
331
  }
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
332
  return parseFocusCapsule(content);
286
333
  }
287
334
  function parseFocusCapsule(content) {
@@ -637,109 +684,8 @@ async function showConfig() {
637
684
 
638
685
  // src/commands/doctor.ts
639
686
  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
- }
687
+ import { readdir as readdir2, readFile as readFile3, stat } from "fs/promises";
688
+ import { basename, join as join2, relative as relative2 } from "path";
743
689
 
744
690
  // src/core/artifacts.ts
745
691
  var RSP_AGENTS_BEGIN = "<!-- rsp:begin -->";
@@ -895,9 +841,9 @@ function changeSectionHeading(sectionId) {
895
841
  const guidance = {
896
842
  proposal: "State the intended outcome, why it matters, scope, and non-goals; do not narrate execution.",
897
843
  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.",
844
+ design: "Explain the current approach, boundaries, and necessary tradeoffs; replace obsolete plans while preserving decision reasons and useful outcome comparisons.",
845
+ 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.",
846
+ verify: "Keep required/optional checks and only details needed to judge acceptance, evidence applicability, or locate necessary evidence. Do not repeat check results or retain commands, counts, or review steps merely because they occurred. Preserve applicable coverage, gaps, and distinct review/human acceptance; no run history.",
901
847
  blockers: "Name unresolved decisions or dependencies that prevent progress; use none when there are no blockers."
902
848
  };
903
849
  return `${renderDocumentSectionHeading(CHANGE_DOCUMENT_SCHEMA, sectionId)}
@@ -911,14 +857,13 @@ function renderRspAgentsBlock(runtime) {
911
857
 
912
858
  RSP tracks current work, stable specs, and archives under \`.rsp/\`.
913
859
 
914
- Read in order using supplied or confirmed paths; discover only missing paths or applicable ancestor instructions, without overlapping whole-tree scans:
860
+ Use supplied or confirmed paths; discover only missing paths or applicable ancestor instructions, without overlapping whole-tree scans:
915
861
  1. Nearest \`AGENTS.md\` for project or module instructions.
916
862
  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.
863
+ 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.
864
+ 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
865
 
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.
866
+ 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
867
  Do not treat \`.rsp/specs/\` or \`.rsp/changes/\` as replacements for nearest \`AGENTS.md\` or \`CONTEXT.md\`.
923
868
 
924
869
  ${selection}
@@ -1031,8 +976,8 @@ async function checkForUpdates(current) {
1031
976
 
1032
977
  // src/commands/skills.ts
1033
978
  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";
979
+ import { chmod, copyFile, mkdir, mkdtemp, readdir, readFile as readFile2, rename, rm } from "fs/promises";
980
+ import { dirname, join, relative } from "path";
1036
981
  var DEFAULT_PACKAGED_SKILL_NAMES = [
1037
982
  "rsp",
1038
983
  "rsp-shape",
@@ -1057,7 +1002,7 @@ function unsupportedEntry(path, label) {
1057
1002
  return new ManagedPathError(path, `unsupported entry in the ${label} tree: ${path}`);
1058
1003
  }
1059
1004
  async function inspectPackagedSkills(packageRoot) {
1060
- const skillsRoot = join2(packageRoot, "skills");
1005
+ const skillsRoot = join(packageRoot, "skills");
1061
1006
  const rootInspection = inspectManagedDirectory(skillsRoot, "packaged Skills root");
1062
1007
  if (rootInspection.issue)
1063
1008
  throw rootInspection.issue;
@@ -1066,7 +1011,7 @@ async function inspectPackagedSkills(packageRoot) {
1066
1011
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
1067
1012
  if (entry.name.startsWith("."))
1068
1013
  continue;
1069
- const root = join2(skillsRoot, entry.name);
1014
+ const root = join(skillsRoot, entry.name);
1070
1015
  if (!entry.isDirectory())
1071
1016
  throw unsupportedEntry(root, "packaged Skills");
1072
1017
  const inspection = await inspectManagedFileTree(root, `packaged Skill ${entry.name}`, { includeHidden: true });
@@ -1118,14 +1063,14 @@ async function treesEqual(source, targetRoot) {
1118
1063
  if (source.files.length !== targetFiles.length || source.files.some((path, index) => path !== targetFiles[index]))
1119
1064
  return false;
1120
1065
  for (const path of source.files) {
1121
- const sourcePath = join2(source.root, path);
1122
- const targetPath = join2(targetRoot, path);
1066
+ const sourcePath = join(source.root, path);
1067
+ const targetPath = join(targetRoot, path);
1123
1068
  const [sourceStats, targetStats] = [lstatSync(sourcePath), lstatSync(targetPath)];
1124
1069
  if (!sourceStats.isFile() || !targetStats.isFile())
1125
1070
  throw unsupportedEntry(!sourceStats.isFile() ? sourcePath : targetPath, `Skill ${source.name}`);
1126
1071
  if ((sourceStats.mode & 511) !== (targetStats.mode & 511))
1127
1072
  return false;
1128
- const [sourceContent, targetContent] = await Promise.all([readFile3(sourcePath), readFile3(targetPath)]);
1073
+ const [sourceContent, targetContent] = await Promise.all([readFile2(sourcePath), readFile2(targetPath)]);
1129
1074
  if (!sourceContent.equals(targetContent))
1130
1075
  return false;
1131
1076
  }
@@ -1139,14 +1084,14 @@ async function inspectPackagedSkillInventory(options = {}) {
1139
1084
  const missingDefaults = DEFAULT_PACKAGED_SKILL_NAMES.filter((name) => !packagedNames.has(name));
1140
1085
  if (missingDefaults.length > 0)
1141
1086
  throw new Error(`packaged Skills missing default Skills: ${missingDefaults.join(", ")}`);
1142
- const manifest = JSON.parse(await readFile3(join2(packageRoot, "package.json"), "utf8"));
1087
+ const manifest = JSON.parse(await readFile2(join(packageRoot, "package.json"), "utf8"));
1143
1088
  if (typeof manifest.name !== "string" || typeof manifest.version !== "string")
1144
1089
  throw new Error("package.json must contain string name and version fields");
1145
1090
  const targetRoot = resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1146
1091
  const defaults = new Set(DEFAULT_PACKAGED_SKILL_NAMES);
1147
1092
  const skills = [];
1148
1093
  for (const skill of packagedSkills) {
1149
- const target = join2(targetRoot, skill.name);
1094
+ const target = join(targetRoot, skill.name);
1150
1095
  const targetStatus = inspectInventoryTarget(target);
1151
1096
  skills.push({
1152
1097
  name: skill.name,
@@ -1154,7 +1099,7 @@ async function inspectPackagedSkillInventory(options = {}) {
1154
1099
  status: targetStatus === "missing" ? "missing" : targetStatus === "divergent" ? isCanonicalSourceProjection(skill.root, target) ? "unchanged" : "divergent" : await treesEqual(skill, target) ? "unchanged" : "divergent"
1155
1100
  });
1156
1101
  }
1157
- const retired = RETIRED_PACKAGED_SKILL_NAMES.filter((name) => inspectInventoryTarget(join2(targetRoot, name)) !== "missing");
1102
+ const retired = RETIRED_PACKAGED_SKILL_NAMES.filter((name) => inspectInventoryTarget(join(targetRoot, name)) !== "missing");
1158
1103
  return {
1159
1104
  retired,
1160
1105
  package: { name: manifest.name, version: manifest.version },
@@ -1165,8 +1110,8 @@ async function inspectPackagedSkillInventory(options = {}) {
1165
1110
  async function copySkillTree(source, targetRoot) {
1166
1111
  await mkdir(targetRoot, { recursive: true });
1167
1112
  for (const path of source.files) {
1168
- const sourcePath = join2(source.root, path);
1169
- const targetPath = join2(targetRoot, path);
1113
+ const sourcePath = join(source.root, path);
1114
+ const targetPath = join(targetRoot, path);
1170
1115
  const stats = lstatSync(sourcePath);
1171
1116
  if (!stats.isFile())
1172
1117
  throw unsupportedEntry(sourcePath, `packaged Skill ${source.name}`);
@@ -1189,7 +1134,7 @@ async function updatePackagedSkills(options = {}) {
1189
1134
  const targetRoot = resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1190
1135
  const result = { installed: [], removed: [], unchanged: [], replaced: [] };
1191
1136
  for (const skill of skills) {
1192
- const target = join2(targetRoot, skill.name);
1137
+ const target = join(targetRoot, skill.name);
1193
1138
  if (isCanonicalSourceProjection(skill.root, target))
1194
1139
  result.unchanged.push(skill.name);
1195
1140
  else if (inspectTarget(target, skill.name) === "missing")
@@ -1200,35 +1145,35 @@ async function updatePackagedSkills(options = {}) {
1200
1145
  result.replaced.push(skill.name);
1201
1146
  }
1202
1147
  for (const name of RETIRED_PACKAGED_SKILL_NAMES) {
1203
- if (inspectTarget(join2(targetRoot, name), name) !== "missing")
1148
+ if (inspectTarget(join(targetRoot, name), name) !== "missing")
1204
1149
  result.removed.push(name);
1205
1150
  }
1206
1151
  if (options.dryRun || result.installed.length + result.replaced.length + result.removed.length === 0)
1207
1152
  return result;
1208
1153
  await mkdir(targetRoot, { recursive: true });
1209
1154
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1210
- const staging = await mkdtemp(join2(targetRoot, ".rsp-skills-"));
1155
+ const staging = await mkdtemp(join(targetRoot, ".rsp-skills-"));
1211
1156
  const completed = [];
1212
1157
  let failure2;
1213
1158
  try {
1214
1159
  for (const skill of skills) {
1215
1160
  if (!result.unchanged.includes(skill.name))
1216
- await copySkillTree(skill, join2(staging, skill.name));
1161
+ await copySkillTree(skill, join(staging, skill.name));
1217
1162
  }
1218
1163
  for (const name of result.removed) {
1219
1164
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1220
- inspectTarget(join2(targetRoot, name), name);
1221
- await rm(join2(targetRoot, name), { recursive: true, force: true });
1165
+ inspectTarget(join(targetRoot, name), name);
1166
+ await rm(join(targetRoot, name), { recursive: true, force: true });
1222
1167
  completed.push(`removed ${name}`);
1223
1168
  }
1224
1169
  for (const skill of skills) {
1225
1170
  if (result.unchanged.includes(skill.name))
1226
1171
  continue;
1227
1172
  resolveManagedDirectoryChain(projectRoot, [".agents", "skills"], "project Skills root");
1228
- const target = join2(targetRoot, skill.name);
1173
+ const target = join(targetRoot, skill.name);
1229
1174
  inspectTarget(target, skill.name);
1230
1175
  await rm(target, { recursive: true, force: true });
1231
- await renamePath(join2(staging, skill.name), target);
1176
+ await renamePath(join(staging, skill.name), target);
1232
1177
  completed.push(`installed ${skill.name}`);
1233
1178
  }
1234
1179
  } catch (error) {
@@ -1275,14 +1220,16 @@ async function runDoctor(options = {}) {
1275
1220
  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
1221
  });
1277
1222
  }
1278
- await checkSpecsTree(checks, reportRuntime);
1279
1223
  await checkArchiveNaming(checks);
1280
- const decisionRecordsConfigValid = await checkConfigSemantics(checks, reportRuntime);
1281
- if (decisionRecordsConfigValid) {
1224
+ const configValid = await checkConfigSemantics(checks, reportRuntime);
1225
+ if (configValid) {
1226
+ await checkSpecsTree(checks, reportRuntime);
1282
1227
  await checkDecisionRecordsDirectory(checks, reportRuntime);
1283
1228
  await checkInactiveDefaultDecisionRecords(checks, reportRuntime);
1284
1229
  }
1285
1230
  await checkActiveChangeConsistency(checks);
1231
+ if (configValid)
1232
+ await checkArchitecture(checks);
1286
1233
  const result = {
1287
1234
  command: "doctor",
1288
1235
  ok: checks.every((check) => check.status !== "issue"),
@@ -1294,6 +1241,42 @@ async function runDoctor(options = {}) {
1294
1241
  };
1295
1242
  return result;
1296
1243
  }
1244
+ async function checkArchitecture(checks) {
1245
+ try {
1246
+ const architecture = await queryArchitecture();
1247
+ if (!architecture.configured) {
1248
+ checks.push({
1249
+ status: "info",
1250
+ code: "architecture_not_configured",
1251
+ label: ARCHITECTURE_FILE,
1252
+ message: "Optional architecture model is not configured."
1253
+ });
1254
+ } else if (architecture.diagnostics.length) {
1255
+ for (const diagnostic of architecture.diagnostics) {
1256
+ checks.push({
1257
+ status: "issue",
1258
+ code: `architecture_${diagnostic.code}`,
1259
+ label: `architecture binding: ${diagnostic.file ?? ARCHITECTURE_FILE}`,
1260
+ message: `${diagnostic.file ?? ARCHITECTURE_FILE}: ${diagnostic.message}`
1261
+ });
1262
+ }
1263
+ } else {
1264
+ checks.push({
1265
+ status: "ok",
1266
+ code: "architecture_valid",
1267
+ label: "architecture structure and document bindings",
1268
+ message: `${architecture.nodes.length} nodes, ${architecture.relations.length} relations, ${architecture.views.length} views. Structural and reference validity does not establish semantic agreement with implementation.`
1269
+ });
1270
+ }
1271
+ } catch (error) {
1272
+ checks.push({
1273
+ status: "issue",
1274
+ code: "architecture_inspection_failed",
1275
+ label: ARCHITECTURE_FILE,
1276
+ message: `${ARCHITECTURE_FILE}: ${toErrorMessage(error)}`
1277
+ });
1278
+ }
1279
+ }
1297
1280
  async function reportProjectRuntime(checks) {
1298
1281
  let sourceMode = false;
1299
1282
  try {
@@ -1389,7 +1372,7 @@ async function checkAgents(checks, reportRuntime) {
1389
1372
  }
1390
1373
  let agents;
1391
1374
  try {
1392
- agents = await readFile4("AGENTS.md", "utf-8");
1375
+ agents = await readFile3("AGENTS.md", "utf-8");
1393
1376
  } catch (error) {
1394
1377
  reportRuntime({
1395
1378
  code: "agents_read_failed",
@@ -1448,7 +1431,7 @@ async function checkSpecsTree(checks, reportRuntime) {
1448
1431
  }
1449
1432
  }
1450
1433
  async function checkArchiveNaming(checks) {
1451
- const archivesDir = join3(RSP_DIR, "archives");
1434
+ const archivesDir = join2(RSP_DIR, "archives");
1452
1435
  const inspection = await inspectArchiveTree({ archivesDir });
1453
1436
  if (inspection.diagnostics.length > 0) {
1454
1437
  checks.push({
@@ -1812,7 +1795,7 @@ function emptyCollectionSummary() {
1812
1795
  }
1813
1796
 
1814
1797
  // src/commands/ready.ts
1815
- import { readFile as readFile5 } from "fs/promises";
1798
+ import { readFile as readFile4 } from "fs/promises";
1816
1799
  function readyError(name, error, kind) {
1817
1800
  return { command: "ready", ok: false, change: name || null, path: null, warnings: [], runtime: [], error, kind };
1818
1801
  }
@@ -1832,7 +1815,7 @@ async function showReady(name) {
1832
1815
  const runtime = [];
1833
1816
  let content;
1834
1817
  try {
1835
- content = await readFile5(srcPath, "utf-8");
1818
+ content = await readFile4(srcPath, "utf-8");
1836
1819
  } catch {
1837
1820
  return readyError(name, { code: "change_read_failed", message: `unable to read .rsp/changes/${name}.md` }, "read");
1838
1821
  }
@@ -1876,7 +1859,7 @@ async function showReady(name) {
1876
1859
  }
1877
1860
 
1878
1861
  // src/commands/show.ts
1879
- import { readFile as readFile6 } from "fs/promises";
1862
+ import { readFile as readFile5 } from "fs/promises";
1880
1863
  function showError(error, runtime = []) {
1881
1864
  const nextActions = error.code === "no_focused_change" ? ["Run: rsp status", "Run: rsp focus <name>", "Or run: rsp create <name>"] : [];
1882
1865
  return { command: "show", ok: false, change: null, contextPaths: [], runtime, nextActions, error };
@@ -1920,7 +1903,7 @@ async function showChange(nameOrFocused, options = {}) {
1920
1903
  const srcPath = workRef.path;
1921
1904
  let content;
1922
1905
  try {
1923
- content = await readFile6(srcPath, "utf-8");
1906
+ content = await readFile5(srcPath, "utf-8");
1924
1907
  } catch {
1925
1908
  return showError({ code: "change_read_failed", message: `unable to read .rsp/changes/${name}.md` }, runtime);
1926
1909
  }
@@ -1949,7 +1932,7 @@ async function showChange(nameOrFocused, options = {}) {
1949
1932
  const markerPath = focusMarkers.get(name);
1950
1933
  let markerContent;
1951
1934
  try {
1952
- markerContent = await readFile6(markerPath);
1935
+ markerContent = await readFile5(markerPath);
1953
1936
  } catch (error) {
1954
1937
  reportRuntime({
1955
1938
  code: "focus_marker_read_failed",
@@ -2850,7 +2833,7 @@ function formatArchiveReady(value) {
2850
2833
  }
2851
2834
 
2852
2835
  // src/cli/commands/inspection.ts
2853
- var configCommand = defineCommand({
2836
+ var configCommand = defineCommand2({
2854
2837
  meta: {
2855
2838
  name: "config",
2856
2839
  description: "Inspect effective project configuration without scanning work state"
@@ -2866,7 +2849,7 @@ var configCommand = defineCommand({
2866
2849
  }, args);
2867
2850
  }
2868
2851
  });
2869
- var specsCommand = defineCommand({
2852
+ var specsCommand = defineCommand2({
2870
2853
  meta: {
2871
2854
  name: "specs",
2872
2855
  description: "Inspect current Specs and Decision Records or run bounded literal search"
@@ -2905,7 +2888,7 @@ var specsCommand = defineCommand({
2905
2888
  }, args);
2906
2889
  }
2907
2890
  });
2908
- var statusCommand = defineCommand({
2891
+ var statusCommand = defineCommand2({
2909
2892
  meta: {
2910
2893
  name: "status",
2911
2894
  description: "Show project status summary with current focus information"
@@ -2953,7 +2936,7 @@ var statusCommand = defineCommand({
2953
2936
  }, args);
2954
2937
  }
2955
2938
  });
2956
- var checkCommand = defineCommand({
2939
+ var checkCommand = defineCommand2({
2957
2940
  meta: {
2958
2941
  name: "check",
2959
2942
  description: "Validate changes (frontmatter, sections, template text, deltas, scenarios)"
@@ -2979,7 +2962,7 @@ var checkCommand = defineCommand({
2979
2962
  }, args);
2980
2963
  }
2981
2964
  });
2982
- var doctorCommand = defineCommand({
2965
+ var doctorCommand = defineCommand2({
2983
2966
  meta: {
2984
2967
  name: "doctor",
2985
2968
  description: "Check RSP setup health and common integration issues"
@@ -3007,7 +2990,7 @@ var doctorCommand = defineCommand({
3007
2990
  }, args);
3008
2991
  }
3009
2992
  });
3010
- var readyCommand = defineCommand({
2993
+ var readyCommand = defineCommand2({
3011
2994
  meta: {
3012
2995
  name: "ready",
3013
2996
  description: "Preview archive readiness for a change without moving it"
@@ -3033,7 +3016,7 @@ var readyCommand = defineCommand({
3033
3016
  }, args);
3034
3017
  }
3035
3018
  });
3036
- var showCommand = defineCommand({
3019
+ var showCommand = defineCommand2({
3037
3020
  meta: {
3038
3021
  name: "show",
3039
3022
  description: "Show change context with readiness signals and relevant paths"
@@ -3064,7 +3047,7 @@ var showCommand = defineCommand({
3064
3047
  }, args);
3065
3048
  }
3066
3049
  });
3067
- var historyCommand = defineCommand({
3050
+ var historyCommand = defineCommand2({
3068
3051
  meta: {
3069
3052
  name: "history",
3070
3053
  description: "Query bounded archived Change summaries or one exact archived WorkRef"
@@ -3130,14 +3113,14 @@ var inspectionCommands = {
3130
3113
  };
3131
3114
 
3132
3115
  // src/cli/commands/setup.ts
3133
- import { defineCommand as defineCommand2 } from "citty";
3116
+ import { defineCommand as defineCommand3 } from "citty";
3134
3117
 
3135
3118
  // src/commands/add-spec.ts
3136
3119
  import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
3137
- import { join as join4 } from "path";
3120
+ import { join as join3 } from "path";
3138
3121
 
3139
3122
  // src/core/lock.ts
3140
- import { mkdir as mkdir2, readFile as readFile7, unlink, writeFile } from "fs/promises";
3123
+ import { mkdir as mkdir2, readFile as readFile6, unlink, writeFile } from "fs/promises";
3141
3124
  async function withRspLock(operation, fn) {
3142
3125
  requireManagedDirectory(RSP_DIR, "RSP root", { allowMissing: true });
3143
3126
  await mkdir2(RSP_DIR, { recursive: true });
@@ -3162,7 +3145,7 @@ ${(/* @__PURE__ */ new Date()).toISOString()}`, { flag: "wx" });
3162
3145
  }
3163
3146
  async function handleStaleLock(operation) {
3164
3147
  try {
3165
- const content = await readFile7(LOCK_PATH, "utf-8");
3148
+ const content = await readFile6(LOCK_PATH, "utf-8");
3166
3149
  const lines = content.trim().split("\n");
3167
3150
  const pid = Number(lines[0]);
3168
3151
  if (pid && Number.isFinite(pid)) {
@@ -3220,10 +3203,10 @@ async function addSpec(name, projectName = "project") {
3220
3203
  return { ok: false, message: `.rsp/config.yaml could not be parsed: ${toErrorMessage(error)}` };
3221
3204
  }
3222
3205
  return withRspLock("add-spec", async () => {
3223
- const specsDir = join4(RSP_DIR, "specs");
3206
+ const specsDir = join3(RSP_DIR, "specs");
3224
3207
  const segments = name.split("/");
3225
3208
  const parent = resolveManagedDirectoryChain(specsDir, segments.slice(0, -1), "spec path");
3226
- const path = join4(parent, `${segments.at(-1)}.md`);
3209
+ const path = join3(parent, `${segments.at(-1)}.md`);
3227
3210
  const inspection = await inspectManagedFileTree(specsDir, "Specs");
3228
3211
  if (inspection.issues.length > 0)
3229
3212
  throw inspection.issues[0];
@@ -3243,30 +3226,30 @@ async function addSpec(name, projectName = "project") {
3243
3226
 
3244
3227
  // src/commands/init.ts
3245
3228
  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";
3229
+ import { mkdir as mkdir4, readdir as readdir3, readFile as readFile8 } from "fs/promises";
3230
+ import { join as join5 } from "path";
3248
3231
 
3249
3232
  // src/core/setup-files.ts
3250
3233
  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";
3234
+ 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";
3235
+ import { dirname as dirname2, join as join4 } from "path";
3253
3236
  async function updateSetupFile(path, render) {
3254
3237
  const exists = requireManagedFile(path, "setup file", { allowMissing: true });
3255
- const current = exists ? await readFile8(path, "utf8") : null;
3238
+ const current = exists ? await readFile7(path, "utf8") : null;
3256
3239
  const next = render(current);
3257
3240
  if (next === current)
3258
3241
  return false;
3259
3242
  if (exists)
3260
3243
  await access(path, constants.W_OK);
3261
- const temporary = await mkdtemp2(join5(dirname2(path), ".rsp-write-"));
3262
- const prepared = join5(temporary, "next");
3244
+ const temporary = await mkdtemp2(join4(dirname2(path), ".rsp-write-"));
3245
+ const prepared = join4(temporary, "next");
3263
3246
  let failure2;
3264
3247
  try {
3265
3248
  await writeFile3(prepared, next, { flag: "wx" });
3266
3249
  if (exists)
3267
3250
  await chmod2(prepared, (await stat2(path)).mode & 511);
3268
3251
  const stillExists = requireManagedFile(path, "setup file", { allowMissing: true });
3269
- if (stillExists !== exists || stillExists && await readFile8(path, "utf8") !== current)
3252
+ if (stillExists !== exists || stillExists && await readFile7(path, "utf8") !== current)
3270
3253
  throw new Error(`Setup file changed during update: ${path}`);
3271
3254
  if (exists)
3272
3255
  await rename2(prepared, path);
@@ -3307,7 +3290,7 @@ async function initProject(args = {}) {
3307
3290
  const pathIssue = await validateDecisionRecordsFilesystemPath(decisionRecordsPath);
3308
3291
  if (pathIssue)
3309
3292
  throw new Error(pathIssue);
3310
- const dirs = [join6(RSP_DIR, "specs"), CHANGES_DIR, FOCUS_DIR, join6(RSP_DIR, "archives"), decisionRecordsPath];
3293
+ const dirs = [join5(RSP_DIR, "specs"), CHANGES_DIR, FOCUS_DIR, join5(RSP_DIR, "archives"), decisionRecordsPath];
3311
3294
  for (const path of dirs)
3312
3295
  resolveManagedDirectoryChain(process.cwd(), path.split("/"), "project directory");
3313
3296
  const completed = [];
@@ -3327,12 +3310,12 @@ async function initProject(args = {}) {
3327
3310
  }
3328
3311
  await ensureFile(CONFIG_PATH, generateConfigTemplate());
3329
3312
  clearConfigCache();
3330
- await ensureFile(join6(RSP_DIR, "specs/design.md"), generateDesignContent(projectName));
3313
+ await ensureFile(join5(RSP_DIR, "specs/design.md"), generateDesignContent(projectName));
3331
3314
  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");
3315
+ await ensureFile(join5(decisionRecordsPath, ".gitkeep"), "");
3316
+ await ensureFile(join5(CHANGES_DIR, ".gitkeep"), "");
3317
+ await ensureFile(join5(FOCUS_DIR, ".gitkeep"), "");
3318
+ await ensureFile(join5(RSP_DIR, ".gitignore"), "# Transient files that should not be committed\n.lock\n");
3336
3319
  if (args.withProjectSetup) {
3337
3320
  const work = resolveWorkRef("project-setup", { executable: true });
3338
3321
  await ensureFile(work.path, generateChangeContent("project-setup"));
@@ -3347,7 +3330,7 @@ async function initProject(args = {}) {
3347
3330
  if (runtime.mode === "package" && await updateSetupFile(PROJECT_VERSION_PATH, () => `${version}
3348
3331
  `))
3349
3332
  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 };
3333
+ 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
3334
  } catch (error) {
3352
3335
  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
3336
  }
@@ -3356,17 +3339,17 @@ async function initProject(args = {}) {
3356
3339
 
3357
3340
  // src/commands/update.ts
3358
3341
  import { existsSync as existsSync3 } from "fs";
3359
- import { readFile as readFile12, unlink as unlink3 } from "fs/promises";
3360
- import { join as join8 } from "path";
3342
+ import { readFile as readFile11, unlink as unlink3 } from "fs/promises";
3343
+ import { join as join7 } from "path";
3361
3344
 
3362
3345
  // src/commands/archive-index-migration.ts
3363
- import { readFile as readFile10 } from "fs/promises";
3364
- import { join as join7 } from "path";
3346
+ import { readFile as readFile9 } from "fs/promises";
3347
+ import { join as join6 } from "path";
3365
3348
  async function isLegacyArchiveIndex() {
3366
- const path = join7(ARCHIVES_DIR, "INDEX.md");
3349
+ const path = join6(ARCHIVES_DIR, "INDEX.md");
3367
3350
  if (!requireManagedFile(path, "legacy archive index", { allowMissing: true }))
3368
3351
  return false;
3369
- return isLegacyArchiveIndexContent(await readFile10(path, "utf-8"));
3352
+ return isLegacyArchiveIndexContent(await readFile9(path, "utf-8"));
3370
3353
  }
3371
3354
  function isLegacyArchiveIndexContent(content) {
3372
3355
  try {
@@ -3378,7 +3361,7 @@ function isLegacyArchiveIndexContent(content) {
3378
3361
  }
3379
3362
 
3380
3363
  // src/commands/specs-index-migration.ts
3381
- import { readFile as readFile11, unlink as unlink2 } from "fs/promises";
3364
+ import { readFile as readFile10, unlink as unlink2 } from "fs/promises";
3382
3365
  import { dirname as dirname3, resolve } from "path";
3383
3366
  async function inspectGeneratedSpecsIndexMigration(cwd = process.cwd()) {
3384
3367
  const inspection = await inspectSpecs({ cwd, allowMissingDecisionRecords: true });
@@ -3393,7 +3376,7 @@ async function removeGeneratedSpecsIndex(path) {
3393
3376
  resolveManagedDirectoryChain(process.cwd(), dirname3(path).split("/"), "Specs parent");
3394
3377
  if (!requireManagedFile(path, "generated Specs index", { allowMissing: true }))
3395
3378
  return false;
3396
- if (!isRecognizedGeneratedSpecsIndex(await readFile11(resolve(path), "utf8"), path))
3379
+ if (!isRecognizedGeneratedSpecsIndex(await readFile10(resolve(path), "utf8"), path))
3397
3380
  throw new Error(`Specs index is no longer generated; left untouched: ${path}`);
3398
3381
  await unlink2(path);
3399
3382
  return true;
@@ -3418,12 +3401,12 @@ async function updateProject(options = {}) {
3418
3401
  return { ok: false, actions: [], updated: false, events: [{ type: "migration-diagnostics", diagnostics: rules.diagnostics }], migration };
3419
3402
  requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true });
3420
3403
  resolveManagedDirectoryChain(process.cwd(), [RSP_DIR, "archives"], "archive parent");
3421
- requireManagedFile(join8(RSP_DIR, "archives/INDEX.md"), "archive index", { allowMissing: true });
3404
+ requireManagedFile(join7(RSP_DIR, "archives/INDEX.md"), "archive index", { allowMissing: true });
3422
3405
  const plan = await inspectGeneratedSpecsIndexMigration();
3423
3406
  if (!plan.inspectionComplete || plan.ownerControlled.length)
3424
3407
  throw new Error(`Generated Specs-index migration requires owner review before update: ${[...plan.ownerControlled, ...plan.diagnostics].join("; ")}`);
3425
3408
  const projectName = await detectProjectName();
3426
- const agents = requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true }) ? await readFile12("AGENTS.md", "utf8") : null;
3409
+ const agents = requireManagedFile("AGENTS.md", "AGENTS.md", { allowMissing: true }) ? await readFile11("AGENTS.md", "utf8") : null;
3427
3410
  const refreshAgents = (current) => upsertRspAgentsBlock(current ?? `# ${projectName}
3428
3411
 
3429
3412
  `, runtime).content;
@@ -3464,7 +3447,7 @@ async function updateProject(options = {}) {
3464
3447
  record(`generated Specs index removed: ${path}`);
3465
3448
  }
3466
3449
  if (await isLegacyArchiveIndex()) {
3467
- await unlink3(join8(RSP_DIR, "archives/INDEX.md"));
3450
+ await unlink3(join7(RSP_DIR, "archives/INDEX.md"));
3468
3451
  record("legacy Archive Index removed");
3469
3452
  }
3470
3453
  if (await updateSetupFile("AGENTS.md", refreshAgents))
@@ -3578,7 +3561,7 @@ function presentUpdate(result, dryRun = false) {
3578
3561
  }
3579
3562
 
3580
3563
  // src/cli/commands/setup.ts
3581
- var initCommand = defineCommand2({
3564
+ var initCommand = defineCommand3({
3582
3565
  meta: {
3583
3566
  name: "init",
3584
3567
  description: "Scaffold .rsp/ and ensure AGENTS.md contains the RSP entry block"
@@ -3606,7 +3589,7 @@ var initCommand = defineCommand2({
3606
3589
  }, args);
3607
3590
  }
3608
3591
  });
3609
- var addSpecCommand = defineCommand2({
3592
+ var addSpecCommand = defineCommand3({
3610
3593
  meta: {
3611
3594
  name: "spec",
3612
3595
  description: "Create .rsp/specs/<name>.md for direct Specs queries"
@@ -3626,7 +3609,7 @@ var addSpecCommand = defineCommand2({
3626
3609
  }, args);
3627
3610
  }
3628
3611
  });
3629
- var addCommand = defineCommand2({
3612
+ var addCommand = defineCommand3({
3630
3613
  meta: {
3631
3614
  name: "add",
3632
3615
  description: "Add an optional durable spec file"
@@ -3635,7 +3618,7 @@ var addCommand = defineCommand2({
3635
3618
  spec: addSpecCommand
3636
3619
  }
3637
3620
  });
3638
- var updateCommand = defineCommand2({
3621
+ var updateCommand = defineCommand3({
3639
3622
  meta: {
3640
3623
  name: "update",
3641
3624
  description: "Update the complete pinned environment and remove retired managed assets"
@@ -3660,7 +3643,7 @@ var setupCommands = {
3660
3643
  };
3661
3644
 
3662
3645
  // src/cli/commands/skills.ts
3663
- import { defineCommand as defineCommand3 } from "citty";
3646
+ import { defineCommand as defineCommand4 } from "citty";
3664
3647
 
3665
3648
  // src/cli/presenters/skills.ts
3666
3649
  function presentPackagedSkillInventory(inventory, json = false) {
@@ -3678,7 +3661,7 @@ function presentPackagedSkillInventory(inventory, json = false) {
3678
3661
  }
3679
3662
 
3680
3663
  // src/cli/commands/skills.ts
3681
- var skillsListCommand = defineCommand3({
3664
+ var skillsListCommand = defineCommand4({
3682
3665
  meta: { name: "list", description: "Inspect the complete package-owned Skill inventory" },
3683
3666
  args: { ...jsonArgs },
3684
3667
  async run({ args }) {
@@ -3689,19 +3672,19 @@ var skillsListCommand = defineCommand3({
3689
3672
  }
3690
3673
  });
3691
3674
  var skillsCommands = {
3692
- skills: defineCommand3({
3675
+ skills: defineCommand4({
3693
3676
  meta: { name: "skills", description: "Inspect Skills; use init or update to manage the complete environment" },
3694
3677
  subCommands: { list: skillsListCommand }
3695
3678
  })
3696
3679
  };
3697
3680
 
3698
3681
  // src/cli/commands/work.ts
3699
- import { defineCommand as defineCommand4 } from "citty";
3682
+ import { defineCommand as defineCommand5 } from "citty";
3700
3683
 
3701
3684
  // src/commands/archive.ts
3702
3685
  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";
3686
+ import { mkdir as mkdir5, readFile as readFile12, rename as rename3, unlink as unlink4 } from "fs/promises";
3687
+ import { basename as basename2, join as join8 } from "path";
3705
3688
  async function archiveChange(name) {
3706
3689
  if (!name) {
3707
3690
  return { ok: false, kind: "usage", message: "rsp archive <name>" };
@@ -3718,7 +3701,7 @@ async function archiveChange(name) {
3718
3701
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3719
3702
  const base = basename2(workRef.name);
3720
3703
  const archiveName = resolveArchiveName(archiveSubdir, date, base);
3721
- const content = await readFile13(srcPath, "utf-8");
3704
+ const content = await readFile12(srcPath, "utf-8");
3722
3705
  const configInspection = await inspectRspConfig();
3723
3706
  if (configInspection.issues.length > 0) {
3724
3707
  return {
@@ -3747,7 +3730,7 @@ async function archiveChange(name) {
3747
3730
  };
3748
3731
  }
3749
3732
  await mkdir5(archiveSubdir, { recursive: true });
3750
- await rename3(srcPath, join9(archiveSubdir, archiveName));
3733
+ await rename3(srcPath, join8(archiveSubdir, archiveName));
3751
3734
  const postArchiveWarnings = [];
3752
3735
  let focusCleared = false;
3753
3736
  if (existsSync4(focusEntry)) {
@@ -3862,11 +3845,11 @@ async function createChange(name, summary = "", kind, options = {}) {
3862
3845
  }
3863
3846
 
3864
3847
  // src/commands/focus.ts
3865
- import { Buffer as Buffer2 } from "buffer";
3848
+ import { Buffer } from "buffer";
3866
3849
  import { randomUUID } from "crypto";
3867
3850
  import { existsSync as existsSync6 } from "fs";
3868
3851
  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";
3852
+ import { basename as basename3, dirname as dirname5, join as join9 } from "path";
3870
3853
  async function focusChange(name, options = {}) {
3871
3854
  if (!name) {
3872
3855
  return { ok: false, kind: "usage", message: "rsp focus <name>" };
@@ -3901,7 +3884,7 @@ async function readCapsule(source) {
3901
3884
  }
3902
3885
  async function replaceFocusCapsule(path, content) {
3903
3886
  requireManagedFile(path, "focus marker", { allowMissing: true });
3904
- const temporaryPath = join10(dirname5(path), `.${basename3(path)}.${randomUUID()}.tmp`);
3887
+ const temporaryPath = join9(dirname5(path), `.${basename3(path)}.${randomUUID()}.tmp`);
3905
3888
  let handle;
3906
3889
  try {
3907
3890
  handle = await open(temporaryPath, "wx");
@@ -3934,13 +3917,13 @@ async function readBoundedStdin() {
3934
3917
  const chunks = [];
3935
3918
  let size = 0;
3936
3919
  for await (const chunk of process.stdin) {
3937
- const buffer = Buffer2.isBuffer(chunk) ? chunk : Buffer2.from(chunk);
3920
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
3938
3921
  size += buffer.byteLength;
3939
3922
  if (size > MAX_FOCUS_CAPSULE_BYTES)
3940
3923
  throw new Error(`focus capsule exceeds ${MAX_FOCUS_CAPSULE_BYTES} UTF-8 bytes`);
3941
3924
  chunks.push(buffer);
3942
3925
  }
3943
- return Buffer2.concat(chunks, size);
3926
+ return Buffer.concat(chunks, size);
3944
3927
  }
3945
3928
  async function unfocusChange(name) {
3946
3929
  if (!name) {
@@ -3975,8 +3958,8 @@ function workRefFailure(error) {
3975
3958
  // src/commands/group.ts
3976
3959
  import { randomUUID as randomUUID2 } from "crypto";
3977
3960
  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";
3961
+ 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";
3962
+ import { join as join10 } from "path";
3980
3963
  var ChangeGroupError = class extends Error {
3981
3964
  name = "ChangeGroupError";
3982
3965
  };
@@ -4037,14 +4020,14 @@ async function closeChangeGroup(name) {
4037
4020
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4038
4021
  const archiveName = resolveArchiveName(archiveDirectory, date, "brief");
4039
4022
  await mkdir8(archiveDirectory, { recursive: true });
4040
- await rename5(ref.path, join11(archiveDirectory, archiveName));
4023
+ await rename5(ref.path, join10(archiveDirectory, archiveName));
4041
4024
  const warnings = [];
4042
4025
  try {
4043
4026
  await cleanupEmptyParentDirs(ref.path, CHANGES_DIR);
4044
4027
  } catch (error) {
4045
4028
  warnings.push(`changes directory cleanup failed: ${toErrorMessage(error)}`);
4046
4029
  }
4047
- return { ok: true, action: "close", groupName, archivePath: join11(archiveDirectory, archiveName), warnings };
4030
+ return { ok: true, action: "close", groupName, archivePath: join10(archiveDirectory, archiveName), warnings };
4048
4031
  });
4049
4032
  } catch (error) {
4050
4033
  if (error instanceof WorkRefError || error instanceof ChangeGroupError) {
@@ -4068,8 +4051,8 @@ async function reopenChangeGroup(name, options) {
4068
4051
  return await withRspLock("reopen-change-group", async () => {
4069
4052
  const warnings = [];
4070
4053
  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}`);
4054
+ await requireEmptyGroupRecoverySubtree(join10(CHANGES_DIR, groupName), `Change Group work subtree for ${groupName}`);
4055
+ await requireEmptyGroupRecoverySubtree(join10(FOCUS_DIR, groupName), `Change Group focus subtree for ${groupName}`);
4073
4056
  const ref = resolveWorkRef(`${groupName}/brief`);
4074
4057
  if (ref.kind !== "group-brief")
4075
4058
  throw new ChangeGroupError(`invalid Change Group name: ${name}`);
@@ -4092,13 +4075,13 @@ async function reopenChangeGroup(name, options) {
4092
4075
  }
4093
4076
  if (existsSync7(ref.path))
4094
4077
  throw new ArchiveHistoryError("open_group_exists", `open Change Group already exists: ${groupName}`);
4095
- const archivedContent = await readFile14(record.sourcePath, "utf-8");
4078
+ const archivedContent = await readFile13(record.sourcePath, "utf-8");
4096
4079
  const document = parseRspDocument(archivedContent, GROUP_BRIEF_DOCUMENT_SCHEMA);
4097
4080
  validateArchivedGroupBrief(document, groupName);
4098
4081
  const evidenceKey = `${GROUP_REOPEN_COMPLETION_PREFIX} \`${record.path}\`: ${reason}`;
4099
4082
  const retainedEvidence = /* @__PURE__ */ new Set();
4100
4083
  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);
4084
+ const retainedDocument = retained.sourcePath === record.sourcePath ? document : parseRspDocument(await readFile13(retained.sourcePath, "utf-8"), GROUP_BRIEF_DOCUMENT_SCHEMA);
4102
4085
  for (const item of getGroupReopenEvidence(retainedDocument))
4103
4086
  retainedEvidence.add(item.key);
4104
4087
  }
@@ -4115,7 +4098,7 @@ async function reopenChangeGroup(name, options) {
4115
4098
  );
4116
4099
  const groupDirectory = resolveManagedDirectoryChain(CHANGES_DIR, [groupName], "Change Group path");
4117
4100
  await mkdir8(groupDirectory, { recursive: true });
4118
- const temporaryPath = join11(RSP_DIR, `.group-reopen-${process.pid}-${randomUUID2()}.tmp`);
4101
+ const temporaryPath = join10(RSP_DIR, `.group-reopen-${process.pid}-${randomUUID2()}.tmp`);
4119
4102
  let mutationError;
4120
4103
  try {
4121
4104
  await writeFile5(temporaryPath, reopenedContent, { flag: "wx" });
@@ -4200,7 +4183,7 @@ function collectCloseReasons(group, errors) {
4200
4183
 
4201
4184
  // src/commands/reopen.ts
4202
4185
  import { existsSync as existsSync8 } from "fs";
4203
- import { mkdir as mkdir9, readFile as readFile15, unlink as unlink8, writeFile as writeFile6 } from "fs/promises";
4186
+ import { mkdir as mkdir9, readFile as readFile14, unlink as unlink8, writeFile as writeFile6 } from "fs/promises";
4204
4187
  import { dirname as dirname6 } from "path";
4205
4188
  async function reopenChange(name, options) {
4206
4189
  if (!name) {
@@ -4250,7 +4233,7 @@ async function reopenChange(name, options) {
4250
4233
  const focusEntry = resolveFocusMarkerPath(workRef);
4251
4234
  if (existsSync8(focusEntry))
4252
4235
  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");
4236
+ const archivedContent = await readFile14(record.sourcePath, "utf-8");
4254
4237
  const reopenedContent = appendChecklistItem(
4255
4238
  appendChecklistItem(archivedContent, "tasks", `- [ ] Resolve reopened concern: ${reason}`),
4256
4239
  "verify",
@@ -4420,7 +4403,7 @@ function presentReopen(result) {
4420
4403
 
4421
4404
  // src/cli/commands/work.ts
4422
4405
  function createCreateCommand(deprecatedLite) {
4423
- return defineCommand4({
4406
+ return defineCommand5({
4424
4407
  meta: {
4425
4408
  name: "create",
4426
4409
  description: "Create .rsp/changes/<name>.md [summary]"
@@ -4445,7 +4428,7 @@ function createCreateCommand(deprecatedLite) {
4445
4428
  }
4446
4429
  },
4447
4430
  async run({ args }) {
4448
- const summary = Array.isArray(args._) && args._.length > 1 ? args._.slice(1).join(" ") : "";
4431
+ const summary = args._.slice(1).join(" ");
4449
4432
  await executeCliCommand({
4450
4433
  execute: () => createChange(args.name, summary, args.kind, {
4451
4434
  issue: args.issue,
@@ -4458,7 +4441,7 @@ function createCreateCommand(deprecatedLite) {
4458
4441
  }
4459
4442
  });
4460
4443
  }
4461
- var groupCreateCommand = defineCommand4({
4444
+ var groupCreateCommand = defineCommand5({
4462
4445
  meta: {
4463
4446
  name: "create",
4464
4447
  description: "Create an unfocused .rsp/changes/<group>/00-brief.md"
@@ -4471,18 +4454,18 @@ var groupCreateCommand = defineCommand4({
4471
4454
  }
4472
4455
  },
4473
4456
  async run({ args }) {
4474
- const goal = Array.isArray(args._) && args._.length > 1 ? args._.slice(1).join(" ") : "";
4457
+ const goal = args._.slice(1).join(" ");
4475
4458
  await executeCliCommand({ execute: () => createChangeGroup(args.name, goal), present: presentGroup, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4476
4459
  }
4477
4460
  });
4478
- var groupCommand = defineCommand4({
4461
+ var groupCommand = defineCommand5({
4479
4462
  meta: {
4480
4463
  name: "group",
4481
4464
  description: "Create, close, and explicitly reopen shallow Change Groups"
4482
4465
  },
4483
4466
  subCommands: {
4484
4467
  create: groupCreateCommand,
4485
- close: defineCommand4({
4468
+ close: defineCommand5({
4486
4469
  meta: {
4487
4470
  name: "close",
4488
4471
  description: "Archive a completed Group Brief after all child Changes are archived"
@@ -4498,7 +4481,7 @@ var groupCommand = defineCommand4({
4498
4481
  await executeCliCommand({ execute: () => closeChangeGroup(args.name), present: presentGroup, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4499
4482
  }
4500
4483
  }),
4501
- reopen: defineCommand4({
4484
+ reopen: defineCommand5({
4502
4485
  meta: {
4503
4486
  name: "reopen",
4504
4487
  description: "Restore one archived Group Brief while retaining history"
@@ -4525,7 +4508,7 @@ var groupCommand = defineCommand4({
4525
4508
  })
4526
4509
  }
4527
4510
  });
4528
- var archiveCommand = defineCommand4({
4511
+ var archiveCommand = defineCommand5({
4529
4512
  meta: {
4530
4513
  name: "archive",
4531
4514
  description: "Archive an open change into .rsp/archives/"
@@ -4549,7 +4532,7 @@ var archiveCommand = defineCommand4({
4549
4532
  await executeCliCommand({ execute: () => archiveChange(args.name), present: presentArchive, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4550
4533
  }
4551
4534
  });
4552
- var reopenCommand = defineCommand4({
4535
+ var reopenCommand = defineCommand5({
4553
4536
  meta: {
4554
4537
  name: "reopen",
4555
4538
  description: "Restore one archived Change as focused open work while retaining history"
@@ -4574,7 +4557,7 @@ var reopenCommand = defineCommand4({
4574
4557
  await executeCliCommand({ execute: () => reopenChange(args.name, { from: args.from, reason: args.reason }), present: presentReopen, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4575
4558
  }
4576
4559
  });
4577
- var focusCommand = defineCommand4({
4560
+ var focusCommand = defineCommand5({
4578
4561
  meta: {
4579
4562
  name: "focus",
4580
4563
  description: "Mark an existing change as currently focused in .rsp/focus.d/"
@@ -4594,7 +4577,7 @@ var focusCommand = defineCommand4({
4594
4577
  await executeCliCommand({ execute: () => focusChange(args.name, { capsuleFile: args["capsule-file"] }), present: presentFocus, exitCode: (result) => result.ok ? void 0 : 1 }, args);
4595
4578
  }
4596
4579
  });
4597
- var unfocusCommand = defineCommand4({
4580
+ var unfocusCommand = defineCommand5({
4598
4581
  meta: {
4599
4582
  name: "unfocus",
4600
4583
  description: "Remove a change from the current focus set in .rsp/focus.d/"
@@ -4624,13 +4607,15 @@ function createWorkCommands(deprecatedLite) {
4624
4607
  // src/cli/registry.ts
4625
4608
  function createRootCommand(options) {
4626
4609
  const workCommands = createWorkCommands(options.deprecatedLite);
4627
- return defineCommand5({
4610
+ return defineCommand6({
4628
4611
  meta: {
4629
4612
  name: "rsp",
4630
4613
  version: options.version,
4631
4614
  description: "RSP (Reliable Software Practice), a repository-native engineering workflow for humans and AI agents"
4632
4615
  },
4633
4616
  subCommands: {
4617
+ architecture: architectureCommand,
4618
+ view: viewCommand,
4634
4619
  init: setupCommands.init,
4635
4620
  add: setupCommands.add,
4636
4621
  specs: inspectionCommands.specs,
@@ -4715,7 +4700,7 @@ async function runCli(rawArgs = process.argv.slice(2)) {
4715
4700
  } else {
4716
4701
  const { resolveUiLocale } = await import("./locale-HT44UIUP.mjs");
4717
4702
  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");
4703
+ const { runTui } = await import("./entry-NDASTAI5.mjs");
4719
4704
  const exitCode = await runTui(locale);
4720
4705
  if (exitCode !== 0)
4721
4706
  process.exitCode = exitCode;