@dogsbay/commands 0.2.0-beta.101

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 (86) hide show
  1. package/README.md +137 -0
  2. package/dist/commands/content.d.ts +78 -0
  3. package/dist/commands/content.d.ts.map +1 -0
  4. package/dist/commands/content.js +634 -0
  5. package/dist/commands/content.js.map +1 -0
  6. package/dist/commands/examples.d.ts +49 -0
  7. package/dist/commands/examples.d.ts.map +1 -0
  8. package/dist/commands/examples.js +173 -0
  9. package/dist/commands/examples.js.map +1 -0
  10. package/dist/commands/keys.d.ts +14 -0
  11. package/dist/commands/keys.d.ts.map +1 -0
  12. package/dist/commands/keys.js +87 -0
  13. package/dist/commands/keys.js.map +1 -0
  14. package/dist/commands/link-retarget.d.ts +18 -0
  15. package/dist/commands/link-retarget.d.ts.map +1 -0
  16. package/dist/commands/link-retarget.js +104 -0
  17. package/dist/commands/link-retarget.js.map +1 -0
  18. package/dist/commands/refactor-files.d.ts +27 -0
  19. package/dist/commands/refactor-files.d.ts.map +1 -0
  20. package/dist/commands/refactor-files.js +264 -0
  21. package/dist/commands/refactor-files.js.map +1 -0
  22. package/dist/commands/refactor-keys.d.ts +21 -0
  23. package/dist/commands/refactor-keys.d.ts.map +1 -0
  24. package/dist/commands/refactor-keys.js +224 -0
  25. package/dist/commands/refactor-keys.js.map +1 -0
  26. package/dist/commands/refactor-structure.d.ts +19 -0
  27. package/dist/commands/refactor-structure.d.ts.map +1 -0
  28. package/dist/commands/refactor-structure.js +314 -0
  29. package/dist/commands/refactor-structure.js.map +1 -0
  30. package/dist/commands/reindex.d.ts +10 -0
  31. package/dist/commands/reindex.d.ts.map +1 -0
  32. package/dist/commands/reindex.js +23 -0
  33. package/dist/commands/reindex.js.map +1 -0
  34. package/dist/commands/topicmap-edit.d.ts +65 -0
  35. package/dist/commands/topicmap-edit.d.ts.map +1 -0
  36. package/dist/commands/topicmap-edit.js +194 -0
  37. package/dist/commands/topicmap-edit.js.map +1 -0
  38. package/dist/commands/topicmap.d.ts +13 -0
  39. package/dist/commands/topicmap.d.ts.map +1 -0
  40. package/dist/commands/topicmap.js +69 -0
  41. package/dist/commands/topicmap.js.map +1 -0
  42. package/dist/commands/validate.d.ts +13 -0
  43. package/dist/commands/validate.d.ts.map +1 -0
  44. package/dist/commands/validate.js +753 -0
  45. package/dist/commands/validate.js.map +1 -0
  46. package/dist/commands/where-used.d.ts +16 -0
  47. package/dist/commands/where-used.d.ts.map +1 -0
  48. package/dist/commands/where-used.js +83 -0
  49. package/dist/commands/where-used.js.map +1 -0
  50. package/dist/edits.d.ts +54 -0
  51. package/dist/edits.d.ts.map +1 -0
  52. package/dist/edits.js +158 -0
  53. package/dist/edits.js.map +1 -0
  54. package/dist/engine.d.ts +103 -0
  55. package/dist/engine.d.ts.map +1 -0
  56. package/dist/engine.js +115 -0
  57. package/dist/engine.js.map +1 -0
  58. package/dist/flags.d.ts +31 -0
  59. package/dist/flags.d.ts.map +1 -0
  60. package/dist/flags.js +73 -0
  61. package/dist/flags.js.map +1 -0
  62. package/dist/frontmatter-schema.d.ts +97 -0
  63. package/dist/frontmatter-schema.d.ts.map +1 -0
  64. package/dist/frontmatter-schema.js +240 -0
  65. package/dist/frontmatter-schema.js.map +1 -0
  66. package/dist/index.d.ts +35 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +70 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/indexes.d.ts +175 -0
  71. package/dist/indexes.d.ts.map +1 -0
  72. package/dist/indexes.js +536 -0
  73. package/dist/indexes.js.map +1 -0
  74. package/dist/json-schema.d.ts +10 -0
  75. package/dist/json-schema.d.ts.map +1 -0
  76. package/dist/json-schema.js +50 -0
  77. package/dist/json-schema.js.map +1 -0
  78. package/dist/storage.d.ts +68 -0
  79. package/dist/storage.d.ts.map +1 -0
  80. package/dist/storage.js +193 -0
  81. package/dist/storage.js.map +1 -0
  82. package/dist/workspace.d.ts +30 -0
  83. package/dist/workspace.d.ts.map +1 -0
  84. package/dist/workspace.js +63 -0
  85. package/dist/workspace.js.map +1 -0
  86. package/package.json +47 -0
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Structural refactor commands: split-topic, merge-topics.
3
+ *
4
+ * Both operate line-wise with the shared fence grammar (a `## heading`
5
+ * inside a code example is never structure), then reindex and repair
6
+ * inbound references so links keep landing after the surgery. What
7
+ * cannot be repaired mechanically is issued, never silently dropped.
8
+ */
9
+ import { z } from "zod";
10
+ import { fenceOpenBefore, slugifyHeadingText, transformProseLines } from "@dogsbay/format-dogsbay-md";
11
+ import { dirname } from "@dogsbay/format-topicmap";
12
+ import { normalizeStoragePath } from "../storage.js";
13
+ import { relativeHref, replaceLinkHrefs, replaceIncludePaths, rewriteInboundRefs, splitFrontmatter, } from "../edits.js";
14
+ import { defineCommand } from "../engine.js";
15
+ import { missIssues } from "./refactor-files.js";
16
+ import { contentHash } from "./content.js";
17
+ const fail = (code, message, file) => ({
18
+ data: { applied: false },
19
+ issues: [{ severity: "error", code, message, ...(file ? { file } : {}) }],
20
+ summary: message,
21
+ });
22
+ /** `## Title {#id}` → { title, id }. */
23
+ const parseH2 = (line) => {
24
+ const match = line.match(/^##\s+(.*?)\s*(?:\{#([^}]+)\})?\s*$/);
25
+ return { title: match?.[1] ?? line.replace(/^##\s*/, ""), ...(match?.[2] ? { id: match[2] } : {}) };
26
+ };
27
+ export const splitTopicCommand = defineCommand({
28
+ name: "split-topic",
29
+ writes: "content",
30
+ description: "Split a document at its level-2 headings into sibling topics plus a topic map; inbound anchor links follow their sections",
31
+ input: z
32
+ .object({
33
+ file: z.string().min(1).describe("Workspace-relative .md path to split"),
34
+ expect: z.string().optional().describe("Divergence gate: the file's `fileHash` from topic-read"),
35
+ })
36
+ .strict(),
37
+ positionals: ["file"],
38
+ async run(ctx, input) {
39
+ const file = normalizeStoragePath(input.file);
40
+ const { storage } = ctx.workspace;
41
+ if (!(await storage.exists(file)))
42
+ return fail("split-source-missing", `${file} does not exist`);
43
+ const index = await ctx.workspace.index();
44
+ const doc = index.docs.get(file);
45
+ if (!doc)
46
+ return fail("split-not-a-doc", `${file} is not an indexed markdown document`);
47
+ const content = await storage.read(file);
48
+ if (input.expect !== undefined && input.expect !== contentHash(content)) {
49
+ return fail("stale-expect", `${file} changed since it was read; nothing written. Re-read it with topic-read.`, file);
50
+ }
51
+ // Frontmatter is metadata: `## ` lines inside it (YAML comments,
52
+ // block scalars) are never section boundaries, and the block stays
53
+ // with the preamble page
54
+ const [frontmatterBlock, body] = splitFrontmatter(content);
55
+ const lines = body.split("\n");
56
+ const openBefore = fenceOpenBefore(body);
57
+ const h2Lines = lines
58
+ .map((line, i) => ({ line, i }))
59
+ .filter(({ line, i }) => /^##\s/.test(line) && !openBefore[i])
60
+ .map(({ i }) => i);
61
+ if (h2Lines.length === 0) {
62
+ return fail("split-no-sections", `${file} has no level-2 headings to split at`, file);
63
+ }
64
+ const dir = dirname(file);
65
+ const stem = file.split("/").pop().replace(/\.md$/, "");
66
+ const mapPath = dir ? `${dir}/${stem}.topicmap.yml` : `${stem}.topicmap.yml`;
67
+ if (await storage.exists(mapPath)) {
68
+ return fail("split-map-exists", `${mapPath} already exists`, mapPath);
69
+ }
70
+ // Section boundaries → new sibling files
71
+ const taken = new Set(await storage.list());
72
+ const sections = [];
73
+ for (let s = 0; s < h2Lines.length; s++) {
74
+ const start = h2Lines[s];
75
+ const end = s + 1 < h2Lines.length ? h2Lines[s + 1] : lines.length;
76
+ const { title } = parseH2(lines[start]);
77
+ const base = `${stem}-${slugifyHeadingText(title) || `section-${s + 1}`}`;
78
+ let name = dir ? `${dir}/${base}.md` : `${base}.md`;
79
+ let suffix = 2;
80
+ while (taken.has(name)) {
81
+ name = dir ? `${dir}/${base}-${suffix}.md` : `${base}-${suffix}.md`;
82
+ suffix++;
83
+ }
84
+ taken.add(name);
85
+ const body = lines.slice(start, end).join("\n").replace(/\s+$/, "");
86
+ sections.push({
87
+ path: name,
88
+ title,
89
+ body: `---\ntitle: ${JSON.stringify(title)}\n---\n\n${body}\n`,
90
+ });
91
+ }
92
+ // Write pieces, shrink the original to its preamble, emit the map
93
+ for (const section of sections)
94
+ await storage.write(section.path, section.body);
95
+ const preamble = lines.slice(0, h2Lines[0]).join("\n").replace(/\s+$/, "");
96
+ await storage.write(file, `${frontmatterBlock}${preamble}\n`);
97
+ const mapEntries = [
98
+ ` - navtitle: ${JSON.stringify(doc.title ?? stem)}`,
99
+ ` href: ${stem}.md`,
100
+ ...sections.flatMap((section) => [
101
+ ` - navtitle: ${JSON.stringify(section.title)}`,
102
+ ` href: ${section.path.split("/").pop()}`,
103
+ ]),
104
+ ];
105
+ await storage.write(mapPath, `topics:\n${mapEntries.join("\n")}\n`);
106
+ // Anchor repair: fragments that moved into a section file get their
107
+ // inbound links re-pointed there (needs the POST-split index)
108
+ const newIndex = await ctx.workspace.reindex();
109
+ const issues = [];
110
+ const { changed, misses } = await rewriteInboundRefs(ctx.workspace, newIndex, file, (ref) => {
111
+ const fragment = ref.fragment;
112
+ if (!fragment)
113
+ return null; // whole-file links still land (preamble page)
114
+ if (newIndex.docs.get(file)?.anchors.includes(fragment))
115
+ return null;
116
+ const home = sections.find((section) => newIndex.docs.get(section.path)?.anchors.includes(fragment));
117
+ if (!home) {
118
+ issues.push({
119
+ severity: "warning",
120
+ code: "split-anchor-lost",
121
+ message: `link "${ref.raw}" targets #${fragment}, which no piece of the split carries`,
122
+ file: ref.from,
123
+ });
124
+ return null;
125
+ }
126
+ return `${relativeHref(dirname(ref.from), home.path)}#${fragment}`;
127
+ });
128
+ issues.push(...missIssues(misses));
129
+ ctx.workspace.invalidate();
130
+ return {
131
+ data: {
132
+ applied: true,
133
+ file,
134
+ map: mapPath,
135
+ sections: sections.map(({ path, title }) => ({ path, title })),
136
+ rewrittenFiles: changed,
137
+ },
138
+ issues,
139
+ summary: `${file} split into ${sections.length} section file(s) + ${mapPath}`,
140
+ };
141
+ },
142
+ });
143
+ export const mergeTopicsCommand = defineCommand({
144
+ name: "merge-topics",
145
+ writes: "content",
146
+ description: "Merge source documents into a target as level-2 sections (headings shifted), deleting the sources and re-pointing inbound references",
147
+ input: z
148
+ .object({
149
+ into: z.string().min(1).describe("Workspace-relative .md target"),
150
+ sources: z
151
+ .array(z.string().min(1))
152
+ .min(1)
153
+ .describe("Source .md file merged into the target (repeatable)"),
154
+ expect: z.string().optional().describe("Divergence gate: the TARGET's `fileHash` from topic-read"),
155
+ })
156
+ .strict(),
157
+ positionals: ["into"],
158
+ async run(ctx, input) {
159
+ const into = normalizeStoragePath(input.into);
160
+ const sources = input.sources.map(normalizeStoragePath);
161
+ const { storage } = ctx.workspace;
162
+ if (!(await storage.exists(into)))
163
+ return fail("merge-target-missing", `${into} does not exist`);
164
+ if (sources.includes(into))
165
+ return fail("merge-into-self", "a source cannot be the merge target");
166
+ if (new Set(sources).size !== sources.length)
167
+ return fail("merge-duplicate-source", "duplicate source paths");
168
+ for (const source of sources) {
169
+ if (!(await storage.exists(source)))
170
+ return fail("merge-source-missing", `${source} does not exist`);
171
+ }
172
+ const index = await ctx.workspace.index();
173
+ const intoDir = dirname(into);
174
+ const issues = [];
175
+ // Section anchors are derivable up front — links BETWEEN sources
176
+ // need them before their sections are appended. Uniquified against
177
+ // the target's existing anchors AND each other: two sources named
178
+ // a/intro.md and b/intro.md must not both become {#intro}, or
179
+ // re-pointed links land on the wrong section.
180
+ const sectionAnchors = new Map();
181
+ const takenAnchors = new Set(index.docs.get(into)?.anchors ?? []);
182
+ for (const source of sources) {
183
+ const stem = source.split("/").pop().replace(/\.md$/, "");
184
+ const base = slugifyHeadingText(stem) || "section";
185
+ let anchor = base;
186
+ let suffix = 2;
187
+ while (takenAnchors.has(anchor)) {
188
+ anchor = `${base}-${suffix}`;
189
+ suffix++;
190
+ }
191
+ takenAnchors.add(anchor);
192
+ sectionAnchors.set(source, anchor);
193
+ }
194
+ const intoContent = await storage.read(into);
195
+ if (input.expect !== undefined && input.expect !== contentHash(intoContent)) {
196
+ return fail("stale-expect", `${into} changed since it was read; nothing written. Re-read it with topic-read.`, into);
197
+ }
198
+ let merged = intoContent.replace(/\s+$/, "");
199
+ for (const source of sources) {
200
+ const doc = index.docs.get(source);
201
+ const raw = await storage.read(source);
202
+ const [, body] = splitFrontmatter(raw);
203
+ const stem = source.split("/").pop().replace(/\.md$/, "");
204
+ const title = doc?.title ?? doc?.headings[0]?.text ?? stem;
205
+ const anchor = sectionAnchors.get(source);
206
+ // Headings drop one level so the source becomes a section of the
207
+ // target; H6 has nowhere to go and stays put (issued below)
208
+ let h6 = 0;
209
+ let shifted = transformProseLines(body, (line) => {
210
+ if (/^######\s/.test(line)) {
211
+ h6++;
212
+ return line;
213
+ }
214
+ return line.replace(/^(#{1,5})(\s)/, "$1#$2");
215
+ });
216
+ if (h6 > 0) {
217
+ issues.push({
218
+ severity: "warning",
219
+ code: "merge-heading-depth",
220
+ message: `${source}: ${h6} level-6 heading(s) could not shift deeper`,
221
+ file: source,
222
+ });
223
+ }
224
+ // Rewrite the section body's own references: links to co-merged
225
+ // sources become same-document #anchor links (regardless of
226
+ // directories), and everything else is rebased from the target's
227
+ // directory when the source lived elsewhere
228
+ if (doc) {
229
+ const dirChanged = dirname(source) !== intoDir;
230
+ const linkPairs = new Map();
231
+ for (const link of doc.links) {
232
+ if (!link.target || link.href.startsWith("#"))
233
+ continue;
234
+ if (sources.includes(link.target) || link.target === source) {
235
+ const fragment = link.fragment ?? sectionAnchors.get(link.target === source ? source : link.target);
236
+ linkPairs.set(link.href, `#${fragment}`);
237
+ }
238
+ else if (dirChanged) {
239
+ const fragment = link.fragment ? `#${link.fragment}` : "";
240
+ linkPairs.set(link.href, relativeHref(intoDir, link.target) + fragment);
241
+ }
242
+ }
243
+ shifted = replaceLinkHrefs(shifted, linkPairs);
244
+ if (dirChanged) {
245
+ const includePairs = new Map();
246
+ for (const include of doc.includes) {
247
+ includePairs.set(include.raw, relativeHref(intoDir, include.target));
248
+ }
249
+ shifted = replaceIncludePaths(shifted, includePairs);
250
+ }
251
+ }
252
+ merged += `\n\n## ${title} {#${anchor}}\n\n${shifted.trim()}\n`;
253
+ }
254
+ await storage.write(into, `${merged.replace(/\s+$/, "")}\n`);
255
+ for (const source of sources)
256
+ await storage.delete(source);
257
+ // Re-point inbound references using the merged target's real anchors
258
+ const newIndex = await ctx.workspace.reindex();
259
+ const mergedAnchors = newIndex.docs.get(into)?.anchors ?? [];
260
+ const rewritten = [];
261
+ for (const source of sources) {
262
+ const anchor = sectionAnchors.get(source);
263
+ const { changed, misses } = await rewriteInboundRefs(ctx.workspace, index, source, (ref) => {
264
+ if (ref.from === into || sources.includes(ref.from))
265
+ return null; // gone or self
266
+ const base = relativeHref(dirname(ref.from), into);
267
+ if (ref.kind === "topicmap") {
268
+ issues.push({
269
+ severity: "warning",
270
+ code: "merge-map-entry",
271
+ message: `topic-map entry "${ref.raw}" now points at ${into} — review for duplicate entries`,
272
+ file: ref.from,
273
+ });
274
+ return base;
275
+ }
276
+ if (ref.kind === "include") {
277
+ issues.push({
278
+ severity: "warning",
279
+ code: "merge-include-widened",
280
+ message: `include "${ref.raw}" now splices the whole merged ${into}`,
281
+ file: ref.from,
282
+ });
283
+ return base;
284
+ }
285
+ if (ref.fragment && mergedAnchors.includes(ref.fragment)) {
286
+ return `${base}#${ref.fragment}`;
287
+ }
288
+ if (ref.fragment) {
289
+ issues.push({
290
+ severity: "warning",
291
+ code: "merge-anchor-lost",
292
+ message: `link "${ref.raw}": #${ref.fragment} did not survive the merge — re-pointed at the section heading`,
293
+ file: ref.from,
294
+ });
295
+ }
296
+ return `${base}#${anchor}`;
297
+ });
298
+ issues.push(...missIssues(misses));
299
+ rewritten.push(...changed);
300
+ }
301
+ ctx.workspace.invalidate();
302
+ return {
303
+ data: {
304
+ applied: true,
305
+ into,
306
+ merged: sources.map((source) => ({ source, anchor: sectionAnchors.get(source) })),
307
+ rewrittenFiles: [...new Set(rewritten)],
308
+ },
309
+ issues,
310
+ summary: `${sources.length} topic(s) merged into ${into}`,
311
+ };
312
+ },
313
+ });
314
+ //# sourceMappingURL=refactor-structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactor-structure.js","sourceRoot":"","sources":["../../src/commands/refactor-structure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `reindex` — rebuild the workspace indexes and report what's in them.
3
+ *
4
+ * One-shot CLI runs build indexes lazily anyway; this command exists
5
+ * for long-lived hosts (JSON-RPC server, MCP, watch mode) and as the
6
+ * quick "what does the engine see" probe.
7
+ */
8
+ import { z } from "zod";
9
+ export declare const reindexCommand: import("../engine.js").CommandDef<z.ZodObject<{}, z.core.$strict>>;
10
+ //# sourceMappingURL=reindex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reindex.d.ts","sourceRoot":"","sources":["../../src/commands/reindex.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,cAAc,oEAYzB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `reindex` — rebuild the workspace indexes and report what's in them.
3
+ *
4
+ * One-shot CLI runs build indexes lazily anyway; this command exists
5
+ * for long-lived hosts (JSON-RPC server, MCP, watch mode) and as the
6
+ * quick "what does the engine see" probe.
7
+ */
8
+ import { z } from "zod";
9
+ import { defineCommand } from "../engine.js";
10
+ export const reindexCommand = defineCommand({
11
+ name: "reindex",
12
+ writes: "none",
13
+ description: "Rebuild the workspace indexes and print their statistics",
14
+ input: z.object({}).strict(),
15
+ async run(ctx) {
16
+ const index = await ctx.workspace.reindex();
17
+ return {
18
+ data: { stats: index.stats },
19
+ summary: `${index.stats.docs} doc(s), ${index.stats.maps} map(s), ${index.stats.keys} key(s), ${index.stats.links} link(s), ${index.stats.includes} include(s)`,
20
+ };
21
+ },
22
+ });
23
+ //# sourceMappingURL=reindex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reindex.js","sourceRoot":"","sources":["../../src/commands/reindex.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;IAC1C,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,MAAM;IACd,WAAW,EAAE,0DAA0D;IACvE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAC5B,KAAK,CAAC,GAAG,CAAC,GAAG;QACX,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;QAC5C,OAAO;YACL,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;YAC5B,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,KAAK,CAAC,KAAK,aAAa,KAAK,CAAC,KAAK,CAAC,QAAQ,aAAa;SAChK,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Structure verbs over topic maps (`*.topicmap.yml`) — `map-list`,
3
+ * `map-add-ref`, `map-move-ref`, `map-remove-ref`, `map-set-props`
4
+ * (plans/agent-broker.md Phase 3; plans/topicmap-editor.md Phase 2/4).
5
+ *
6
+ * Every edit goes through `applyMapEdit` in `@dogsbay/format-topicmap`
7
+ * (`edit-source.ts`): the model transforms (`edit.ts`) validate and the
8
+ * change is replayed on the YAML document, so comments, unknown keys and
9
+ * the author's formatting survive (a minimal diff, not a canonical
10
+ * rewrite). SHARED with the IDE's Structure panel: a dangling href, a self-include, moving an entry into
11
+ * its own subtree, or an unresolvable pointer is refused with an issue,
12
+ * not applied — identically for the agent and for a human. This module is
13
+ * the I/O shell: load, existence predicate, write, issue shaping.
14
+ * Entries are addressed by POINTER — a dotted index path like `0.2.1`
15
+ * (`""` is the root) — or, where unambiguous, by `href`.
16
+ */
17
+ import { z } from "zod";
18
+ export declare const mapListCommand: import("../engine.js").CommandDef<z.ZodObject<{
19
+ map: z.ZodString;
20
+ }, z.core.$strict>>;
21
+ export declare const mapAddRefCommand: import("../engine.js").CommandDef<z.ZodObject<{
22
+ map: z.ZodString;
23
+ href: z.ZodOptional<z.ZodString>;
24
+ navtitle: z.ZodOptional<z.ZodString>;
25
+ parent: z.ZodDefault<z.ZodString>;
26
+ index: z.ZodOptional<z.ZodNumber>;
27
+ format: z.ZodOptional<z.ZodEnum<{
28
+ topicmap: "topicmap";
29
+ md: "md";
30
+ }>>;
31
+ toc: z.ZodOptional<z.ZodBoolean>;
32
+ singlePage: z.ZodOptional<z.ZodEnum<{
33
+ yes: "yes";
34
+ children: "children";
35
+ no: "no";
36
+ }>>;
37
+ }, z.core.$strict>>;
38
+ export declare const mapMoveRefCommand: import("../engine.js").CommandDef<z.ZodObject<{
39
+ map: z.ZodString;
40
+ from: z.ZodString;
41
+ toParent: z.ZodOptional<z.ZodString>;
42
+ index: z.ZodOptional<z.ZodNumber>;
43
+ }, z.core.$strict>>;
44
+ export declare const mapRemoveRefCommand: import("../engine.js").CommandDef<z.ZodObject<{
45
+ map: z.ZodString;
46
+ at: z.ZodString;
47
+ keepChildren: z.ZodDefault<z.ZodBoolean>;
48
+ }, z.core.$strict>>;
49
+ export declare const mapSetPropsCommand: import("../engine.js").CommandDef<z.ZodObject<{
50
+ map: z.ZodString;
51
+ at: z.ZodString;
52
+ navtitle: z.ZodOptional<z.ZodNullable<z.ZodString>>;
53
+ href: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
+ format: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
55
+ topicmap: "topicmap";
56
+ md: "md";
57
+ }>>>;
58
+ toc: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
59
+ singlePage: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
60
+ yes: "yes";
61
+ children: "children";
62
+ no: "no";
63
+ }>>>;
64
+ }, z.core.$strict>>;
65
+ //# sourceMappingURL=topicmap-edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topicmap-edit.d.ts","sourceRoot":"","sources":["../../src/commands/topicmap-edit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8DxB,eAAO,MAAM,cAAc;;mBAYzB,CAAC;AAIH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;mBA8B3B,CAAC;AAIH,eAAO,MAAM,iBAAiB;;;;;mBAsB5B,CAAC;AAIH,eAAO,MAAM,mBAAmB;;;;mBA6B9B,CAAC;AAIH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;mBA0B7B,CAAC"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Structure verbs over topic maps (`*.topicmap.yml`) — `map-list`,
3
+ * `map-add-ref`, `map-move-ref`, `map-remove-ref`, `map-set-props`
4
+ * (plans/agent-broker.md Phase 3; plans/topicmap-editor.md Phase 2/4).
5
+ *
6
+ * Every edit goes through `applyMapEdit` in `@dogsbay/format-topicmap`
7
+ * (`edit-source.ts`): the model transforms (`edit.ts`) validate and the
8
+ * change is replayed on the YAML document, so comments, unknown keys and
9
+ * the author's formatting survive (a minimal diff, not a canonical
10
+ * rewrite). SHARED with the IDE's Structure panel: a dangling href, a self-include, moving an entry into
11
+ * its own subtree, or an unresolvable pointer is refused with an issue,
12
+ * not applied — identically for the agent and for a human. This module is
13
+ * the I/O shell: load, existence predicate, write, issue shaping.
14
+ * Entries are addressed by POINTER — a dotted index path like `0.2.1`
15
+ * (`""` is the root) — or, where unambiguous, by `href`.
16
+ */
17
+ import { z } from "zod";
18
+ import { parseTopicMap, applyMapEdit, flattenTopicMap, hrefTarget, } from "@dogsbay/format-topicmap";
19
+ import { normalizeStoragePath } from "../storage.js";
20
+ import { defineCommand } from "../engine.js";
21
+ const fail = (code, message, file, extra = {}) => ({
22
+ data: { applied: false, ...extra },
23
+ issues: [{ severity: "error", code, message, ...(file ? { file } : {}) }],
24
+ summary: message,
25
+ });
26
+ const refused = (r, file) => fail(r.code, r.message, file, r.extra ?? {});
27
+ const isOutput = (x) => typeof x === "object" && x !== null && "data" in x;
28
+ const loadMap = async (ctx, rawFile) => {
29
+ const file = normalizeStoragePath(rawFile);
30
+ const { storage } = ctx.workspace;
31
+ if (!(await storage.exists(file)))
32
+ return fail("map-missing", `${file} does not exist`, file);
33
+ const source = await storage.read(file);
34
+ const { map, errors } = parseTopicMap(source, file);
35
+ if (!map) {
36
+ return {
37
+ data: { applied: false },
38
+ issues: errors.map((e) => ({ severity: "error", code: e.code, message: e.message, file })),
39
+ summary: `${file}: ${errors[0]?.message ?? "invalid topic map"}`,
40
+ };
41
+ }
42
+ const existsFor = async (hrefs) => {
43
+ const known = new Map();
44
+ for (const href of hrefs) {
45
+ const target = hrefTarget(file, href);
46
+ if (target !== undefined && !known.has(target))
47
+ known.set(target, await storage.exists(target));
48
+ }
49
+ return (p) => known.get(p) ?? false;
50
+ };
51
+ return { file, map, source, existsFor };
52
+ };
53
+ const write = async (ctx, file, source) => {
54
+ await ctx.workspace.storage.write(file, source);
55
+ ctx.workspace.invalidate();
56
+ };
57
+ // ─── map-list ───────────────────────────────────────────────────────────────
58
+ export const mapListCommand = defineCommand({
59
+ name: "map-list",
60
+ writes: "none",
61
+ description: "List a topic map's entries with their pointers (dotted index paths), depth, href, format and flags",
62
+ input: z.object({ map: z.string().min(1).describe("Workspace-relative *.topicmap.yml") }).strict(),
63
+ positionals: ["map"],
64
+ async run(ctx, input) {
65
+ const loaded = await loadMap(ctx, input.map);
66
+ if (isOutput(loaded))
67
+ return loaded;
68
+ const entries = flattenTopicMap(loaded.map);
69
+ return { data: { map: loaded.file, title: loaded.map.title, entries }, summary: `${loaded.file}: ${entries.length} entr${entries.length === 1 ? "y" : "ies"}` };
70
+ },
71
+ });
72
+ // ─── map-add-ref ────────────────────────────────────────────────────────────
73
+ export const mapAddRefCommand = defineCommand({
74
+ name: "map-add-ref",
75
+ writes: "structure",
76
+ description: "Add a topicref to a topic map under a parent (pointer or href; root by default) at an index (end by default). Refuses a dangling local href or a self-include",
77
+ input: z
78
+ .object({
79
+ map: z.string().min(1).describe("Workspace-relative *.topicmap.yml"),
80
+ href: z.string().min(1).optional().describe("Target path relative to the map (or / for the root map's dir), or an external URL; optional for a title-only grouping entry"),
81
+ navtitle: z.string().min(1).optional().describe("Navigation label (optional when the target provides a title; required without href)"),
82
+ parent: z.string().default("").describe('Parent pointer ("0.2") or href; "" = root'),
83
+ index: z.number().int().min(0).optional().describe("Position among siblings (default: append)"),
84
+ format: z.enum(["topicmap", "md"]).optional(),
85
+ toc: z.boolean().optional(),
86
+ singlePage: z.enum(["yes", "no", "children"]).optional(),
87
+ })
88
+ .strict(),
89
+ // href is optional (title-only grouping entries), so it is not positional
90
+ positionals: ["map"],
91
+ async run(ctx, input) {
92
+ const loaded = await loadMap(ctx, input.map);
93
+ if (isOutput(loaded))
94
+ return loaded;
95
+ const { file, source } = loaded;
96
+ const exists = await loaded.existsFor(input.href ? [input.href] : []);
97
+ const r = applyMapEdit(source, file, { kind: "add", ...input }, exists);
98
+ if (!r.ok)
99
+ return refused(r, file);
100
+ await write(ctx, file, r.source);
101
+ const issues = [];
102
+ return { data: { applied: true, map: file, pointer: r.pointer, entry: r.entry, target: r.target }, issues, summary: `${file}: added ${input.href ?? input.navtitle} at ${r.pointer || "root"}` };
103
+ },
104
+ });
105
+ // ─── map-move-ref ───────────────────────────────────────────────────────────
106
+ export const mapMoveRefCommand = defineCommand({
107
+ name: "map-move-ref",
108
+ writes: "structure",
109
+ description: "Move an entry (with its subtree) to a new parent and/or index. Refuses moving into its own subtree",
110
+ input: z
111
+ .object({
112
+ map: z.string().min(1).describe("Workspace-relative *.topicmap.yml"),
113
+ from: z.string().min(1).describe("Pointer or href of the entry to move"),
114
+ toParent: z.string().optional().describe('New parent pointer/href ("" = root); default: same parent'),
115
+ index: z.number().int().min(0).optional().describe("Position among the new siblings (default: append)"),
116
+ })
117
+ .strict(),
118
+ positionals: ["map", "from"],
119
+ async run(ctx, input) {
120
+ const loaded = await loadMap(ctx, input.map);
121
+ if (isOutput(loaded))
122
+ return loaded;
123
+ const { file, source } = loaded;
124
+ const r = applyMapEdit(source, file, { kind: "move", ...input });
125
+ if (!r.ok)
126
+ return refused(r, file);
127
+ await write(ctx, file, r.source);
128
+ return { data: { applied: true, map: file, from: r.from, to: r.pointer, entry: r.entry }, summary: `${file}: moved ${r.entry.href ?? r.entry.navtitle ?? r.from} → ${r.pointer}` };
129
+ },
130
+ });
131
+ // ─── map-remove-ref ─────────────────────────────────────────────────────────
132
+ export const mapRemoveRefCommand = defineCommand({
133
+ name: "map-remove-ref",
134
+ writes: "structure",
135
+ description: "Remove an entry. Its children go with it unless keepChildren=true (they are then hoisted into its place)",
136
+ input: z
137
+ .object({
138
+ map: z.string().min(1).describe("Workspace-relative *.topicmap.yml"),
139
+ at: z.string().min(1).describe("Pointer or href of the entry"),
140
+ keepChildren: z.boolean().default(false).describe("Hoist the entry's children into its position instead of removing them"),
141
+ })
142
+ .strict(),
143
+ positionals: ["map", "at"],
144
+ async run(ctx, input) {
145
+ const loaded = await loadMap(ctx, input.map);
146
+ if (isOutput(loaded))
147
+ return loaded;
148
+ const { file, source } = loaded;
149
+ const r = applyMapEdit(source, file, { kind: "remove", ...input });
150
+ if (!r.ok)
151
+ return refused(r, file);
152
+ await write(ctx, file, r.source);
153
+ const issues = [];
154
+ if (r.childrenRemoved) {
155
+ issues.push({ severity: "warning", code: "map-children-removed", message: `${r.childrenRemoved} child entr${r.childrenRemoved === 1 ? "y" : "ies"} removed with ${input.at}`, file });
156
+ }
157
+ return {
158
+ data: { applied: true, map: file, pointer: r.pointer, entry: r.entry, childrenRemoved: r.childrenRemoved, childrenHoisted: r.childrenHoisted },
159
+ issues,
160
+ summary: `${file}: removed ${r.entry.href ?? r.entry.navtitle ?? input.at}${r.childrenHoisted ? ` (hoisted ${r.childrenHoisted} children)` : ""}`,
161
+ };
162
+ },
163
+ });
164
+ // ─── map-set-props ──────────────────────────────────────────────────────────
165
+ export const mapSetPropsCommand = defineCommand({
166
+ name: "map-set-props",
167
+ writes: "structure",
168
+ description: "Set (or with null, unset) an entry's navtitle, href, format, toc, singlePage. A new local href must resolve",
169
+ input: z
170
+ .object({
171
+ map: z.string().min(1).describe("Workspace-relative *.topicmap.yml"),
172
+ at: z.string().min(1).describe("Pointer or href of the entry"),
173
+ navtitle: z.string().min(1).nullable().optional(),
174
+ href: z.string().min(1).nullable().optional(),
175
+ format: z.enum(["topicmap", "md"]).nullable().optional(),
176
+ toc: z.boolean().nullable().optional(),
177
+ singlePage: z.enum(["yes", "no", "children"]).nullable().optional(),
178
+ })
179
+ .strict(),
180
+ positionals: ["map", "at"],
181
+ async run(ctx, input) {
182
+ const loaded = await loadMap(ctx, input.map);
183
+ if (isOutput(loaded))
184
+ return loaded;
185
+ const { file, source } = loaded;
186
+ const exists = await loaded.existsFor(typeof input.href === "string" ? [input.href] : []);
187
+ const r = applyMapEdit(source, file, { kind: "set", ...input }, exists);
188
+ if (!r.ok)
189
+ return refused(r, file);
190
+ await write(ctx, file, r.source);
191
+ return { data: { applied: true, map: file, pointer: r.pointer, changed: r.changed, entry: r.entry }, summary: `${file}: set ${(r.changed ?? []).join(", ")} on ${r.pointer}` };
192
+ },
193
+ });
194
+ //# sourceMappingURL=topicmap-edit.js.map