auden 0.1.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/auden-paths.d.ts +8 -0
  4. package/dist/auden-paths.d.ts.map +1 -0
  5. package/dist/auden-paths.js +10 -0
  6. package/dist/auden-paths.js.map +1 -0
  7. package/dist/bin.d.ts +11 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +13 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/chunk.d.ts +3 -0
  12. package/dist/chunk.d.ts.map +1 -0
  13. package/dist/chunk.js +13 -0
  14. package/dist/chunk.js.map +1 -0
  15. package/dist/commands/doctor.d.ts +13 -0
  16. package/dist/commands/doctor.d.ts.map +1 -0
  17. package/dist/commands/doctor.js +125 -0
  18. package/dist/commands/doctor.js.map +1 -0
  19. package/dist/commands/eval/index.d.ts +2 -0
  20. package/dist/commands/eval/index.d.ts.map +1 -0
  21. package/dist/commands/eval/index.js +2 -0
  22. package/dist/commands/eval/index.js.map +1 -0
  23. package/dist/commands/eval/run.d.ts +38 -0
  24. package/dist/commands/eval/run.d.ts.map +1 -0
  25. package/dist/commands/eval/run.js +179 -0
  26. package/dist/commands/eval/run.js.map +1 -0
  27. package/dist/commands/guides/active.d.ts +2 -0
  28. package/dist/commands/guides/active.d.ts.map +1 -0
  29. package/dist/commands/guides/active.js +38 -0
  30. package/dist/commands/guides/active.js.map +1 -0
  31. package/dist/commands/guides/index.d.ts +2 -0
  32. package/dist/commands/guides/index.d.ts.map +1 -0
  33. package/dist/commands/guides/index.js +13 -0
  34. package/dist/commands/guides/index.js.map +1 -0
  35. package/dist/commands/guides/project.d.ts +13 -0
  36. package/dist/commands/guides/project.d.ts.map +1 -0
  37. package/dist/commands/guides/project.js +71 -0
  38. package/dist/commands/guides/project.js.map +1 -0
  39. package/dist/commands/guides/search.d.ts +8 -0
  40. package/dist/commands/guides/search.d.ts.map +1 -0
  41. package/dist/commands/guides/search.js +46 -0
  42. package/dist/commands/guides/search.js.map +1 -0
  43. package/dist/commands/init.d.ts +43 -0
  44. package/dist/commands/init.d.ts.map +1 -0
  45. package/dist/commands/init.js +436 -0
  46. package/dist/commands/init.js.map +1 -0
  47. package/dist/commands/mcp.d.ts +23 -0
  48. package/dist/commands/mcp.d.ts.map +1 -0
  49. package/dist/commands/mcp.js +55 -0
  50. package/dist/commands/mcp.js.map +1 -0
  51. package/dist/commands/pull.d.ts +38 -0
  52. package/dist/commands/pull.d.ts.map +1 -0
  53. package/dist/commands/pull.js +127 -0
  54. package/dist/commands/pull.js.map +1 -0
  55. package/dist/commands/rules/export.d.ts +140 -0
  56. package/dist/commands/rules/export.d.ts.map +1 -0
  57. package/dist/commands/rules/export.js +635 -0
  58. package/dist/commands/rules/export.js.map +1 -0
  59. package/dist/commands/rules/import.d.ts +33 -0
  60. package/dist/commands/rules/import.d.ts.map +1 -0
  61. package/dist/commands/rules/import.js +122 -0
  62. package/dist/commands/rules/import.js.map +1 -0
  63. package/dist/commands/rules/index.d.ts +2 -0
  64. package/dist/commands/rules/index.d.ts.map +1 -0
  65. package/dist/commands/rules/index.js +13 -0
  66. package/dist/commands/rules/index.js.map +1 -0
  67. package/dist/commands/rules/watch.d.ts +43 -0
  68. package/dist/commands/rules/watch.d.ts.map +1 -0
  69. package/dist/commands/rules/watch.js +125 -0
  70. package/dist/commands/rules/watch.js.map +1 -0
  71. package/dist/commands/status.d.ts +2 -0
  72. package/dist/commands/status.d.ts.map +1 -0
  73. package/dist/commands/status.js +61 -0
  74. package/dist/commands/status.js.map +1 -0
  75. package/dist/commands/suggest.d.ts +8 -0
  76. package/dist/commands/suggest.d.ts.map +1 -0
  77. package/dist/commands/suggest.js +43 -0
  78. package/dist/commands/suggest.js.map +1 -0
  79. package/dist/commands/sync.d.ts +23 -0
  80. package/dist/commands/sync.d.ts.map +1 -0
  81. package/dist/commands/sync.js +193 -0
  82. package/dist/commands/sync.js.map +1 -0
  83. package/dist/commands/verdict/index.d.ts +2 -0
  84. package/dist/commands/verdict/index.d.ts.map +1 -0
  85. package/dist/commands/verdict/index.js +11 -0
  86. package/dist/commands/verdict/index.js.map +1 -0
  87. package/dist/commands/verdict/record.d.ts +18 -0
  88. package/dist/commands/verdict/record.d.ts.map +1 -0
  89. package/dist/commands/verdict/record.js +60 -0
  90. package/dist/commands/verdict/record.js.map +1 -0
  91. package/dist/config.d.ts +96 -0
  92. package/dist/config.d.ts.map +1 -0
  93. package/dist/config.js +246 -0
  94. package/dist/config.js.map +1 -0
  95. package/dist/context/pull.d.ts +40 -0
  96. package/dist/context/pull.d.ts.map +1 -0
  97. package/dist/context/pull.js +46 -0
  98. package/dist/context/pull.js.map +1 -0
  99. package/dist/dashboard-health.d.ts +20 -0
  100. package/dist/dashboard-health.d.ts.map +1 -0
  101. package/dist/dashboard-health.js +24 -0
  102. package/dist/dashboard-health.js.map +1 -0
  103. package/dist/eval-provider.d.ts +30 -0
  104. package/dist/eval-provider.d.ts.map +1 -0
  105. package/dist/eval-provider.js +359 -0
  106. package/dist/eval-provider.js.map +1 -0
  107. package/dist/eval-summary.d.ts +24 -0
  108. package/dist/eval-summary.d.ts.map +1 -0
  109. package/dist/eval-summary.js +30 -0
  110. package/dist/eval-summary.js.map +1 -0
  111. package/dist/feedback/extract.d.ts +6 -0
  112. package/dist/feedback/extract.d.ts.map +1 -0
  113. package/dist/feedback/extract.js +580 -0
  114. package/dist/feedback/extract.js.map +1 -0
  115. package/dist/http-retry.d.ts +23 -0
  116. package/dist/http-retry.d.ts.map +1 -0
  117. package/dist/http-retry.js +54 -0
  118. package/dist/http-retry.js.map +1 -0
  119. package/dist/index.d.ts +6 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +33 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/mcp/client.d.ts +70 -0
  124. package/dist/mcp/client.d.ts.map +1 -0
  125. package/dist/mcp/client.js +121 -0
  126. package/dist/mcp/client.js.map +1 -0
  127. package/dist/mcp/scope.d.ts +30 -0
  128. package/dist/mcp/scope.d.ts.map +1 -0
  129. package/dist/mcp/scope.js +64 -0
  130. package/dist/mcp/scope.js.map +1 -0
  131. package/dist/mcp/server.d.ts +57 -0
  132. package/dist/mcp/server.d.ts.map +1 -0
  133. package/dist/mcp/server.js +427 -0
  134. package/dist/mcp/server.js.map +1 -0
  135. package/dist/mcp/write-items.d.ts +34 -0
  136. package/dist/mcp/write-items.d.ts.map +1 -0
  137. package/dist/mcp/write-items.js +59 -0
  138. package/dist/mcp/write-items.js.map +1 -0
  139. package/dist/rules/deletions-client.d.ts +16 -0
  140. package/dist/rules/deletions-client.d.ts.map +1 -0
  141. package/dist/rules/deletions-client.js +40 -0
  142. package/dist/rules/deletions-client.js.map +1 -0
  143. package/dist/rules/diff.d.ts +19 -0
  144. package/dist/rules/diff.d.ts.map +1 -0
  145. package/dist/rules/diff.js +36 -0
  146. package/dist/rules/diff.js.map +1 -0
  147. package/dist/rules/discover.d.ts +81 -0
  148. package/dist/rules/discover.d.ts.map +1 -0
  149. package/dist/rules/discover.js +307 -0
  150. package/dist/rules/discover.js.map +1 -0
  151. package/dist/rules/file-origin.d.ts +16 -0
  152. package/dist/rules/file-origin.d.ts.map +1 -0
  153. package/dist/rules/file-origin.js +31 -0
  154. package/dist/rules/file-origin.js.map +1 -0
  155. package/dist/rules/global-flag.d.ts +12 -0
  156. package/dist/rules/global-flag.d.ts.map +1 -0
  157. package/dist/rules/global-flag.js +15 -0
  158. package/dist/rules/global-flag.js.map +1 -0
  159. package/dist/rules/import-client.d.ts +37 -0
  160. package/dist/rules/import-client.d.ts.map +1 -0
  161. package/dist/rules/import-client.js +98 -0
  162. package/dist/rules/import-client.js.map +1 -0
  163. package/dist/rules/init-pull.d.ts +34 -0
  164. package/dist/rules/init-pull.d.ts.map +1 -0
  165. package/dist/rules/init-pull.js +43 -0
  166. package/dist/rules/init-pull.js.map +1 -0
  167. package/dist/rules/member-files-client.d.ts +17 -0
  168. package/dist/rules/member-files-client.d.ts.map +1 -0
  169. package/dist/rules/member-files-client.js +29 -0
  170. package/dist/rules/member-files-client.js.map +1 -0
  171. package/dist/rules/path-contains.d.ts +9 -0
  172. package/dist/rules/path-contains.d.ts.map +1 -0
  173. package/dist/rules/path-contains.js +17 -0
  174. package/dist/rules/path-contains.js.map +1 -0
  175. package/dist/rules/payload.d.ts +13 -0
  176. package/dist/rules/payload.d.ts.map +1 -0
  177. package/dist/rules/payload.js +35 -0
  178. package/dist/rules/payload.js.map +1 -0
  179. package/dist/rules/pull-bundle.d.ts +13 -0
  180. package/dist/rules/pull-bundle.d.ts.map +1 -0
  181. package/dist/rules/pull-bundle.js +32 -0
  182. package/dist/rules/pull-bundle.js.map +1 -0
  183. package/dist/rules/watch.d.ts +121 -0
  184. package/dist/rules/watch.d.ts.map +1 -0
  185. package/dist/rules/watch.js +457 -0
  186. package/dist/rules/watch.js.map +1 -0
  187. package/dist/skill-template.d.ts +19 -0
  188. package/dist/skill-template.d.ts.map +1 -0
  189. package/dist/skill-template.js +174 -0
  190. package/dist/skill-template.js.map +1 -0
  191. package/dist/sync-batches.d.ts +37 -0
  192. package/dist/sync-batches.d.ts.map +1 -0
  193. package/dist/sync-batches.js +67 -0
  194. package/dist/sync-batches.js.map +1 -0
  195. package/dist/sync-client.d.ts +22 -0
  196. package/dist/sync-client.d.ts.map +1 -0
  197. package/dist/sync-client.js +38 -0
  198. package/dist/sync-client.js.map +1 -0
  199. package/dist/sync-response.d.ts +23 -0
  200. package/dist/sync-response.d.ts.map +1 -0
  201. package/dist/sync-response.js +22 -0
  202. package/dist/sync-response.js.map +1 -0
  203. package/dist/token-verify.d.ts +14 -0
  204. package/dist/token-verify.d.ts.map +1 -0
  205. package/dist/token-verify.js +30 -0
  206. package/dist/token-verify.js.map +1 -0
  207. package/dist/usage/extract.d.ts +31 -0
  208. package/dist/usage/extract.d.ts.map +1 -0
  209. package/dist/usage/extract.js +200 -0
  210. package/dist/usage/extract.js.map +1 -0
  211. package/dist/usage/providers.d.ts +8 -0
  212. package/dist/usage/providers.d.ts.map +1 -0
  213. package/dist/usage/providers.js +23 -0
  214. package/dist/usage/providers.js.map +1 -0
  215. package/dist/verdict-queue.d.ts +50 -0
  216. package/dist/verdict-queue.d.ts.map +1 -0
  217. package/dist/verdict-queue.js +131 -0
  218. package/dist/verdict-queue.js.map +1 -0
  219. package/package.json +72 -0
@@ -0,0 +1,98 @@
1
+ import { MAX_RULES_IMPORT_BATCH } from '@auden.to/protocol';
2
+ import * as v from 'valibot';
3
+ const NonNegativeIntSchema = v.pipe(v.number(), v.integer(), v.minValue(0));
4
+ // Present only when at least one payload in the batch carried a skill
5
+ // `members` array (older servers omit it entirely).
6
+ const MemberSyncSchema = v.object({
7
+ added: NonNegativeIntSchema,
8
+ updated: NonNegativeIntSchema,
9
+ removed: NonNegativeIntSchema,
10
+ unchanged: NonNegativeIntSchema,
11
+ });
12
+ const ImportSuccessSchema = v.object({
13
+ imported: NonNegativeIntSchema,
14
+ skipped: NonNegativeIntSchema,
15
+ members: v.optional(MemberSyncSchema),
16
+ });
17
+ function trimTrailingSlashes(url) {
18
+ return url.replace(/\/+$/, '');
19
+ }
20
+ // Flush a batch before its serialized body reaches this size. The server's
21
+ // request middleware caps /api/rules/import bodies at 64 MiB (sized for
22
+ // member-less payloads); skill payloads carry member files, so a
23
+ // count-only chunking of 100 large skills could exceed it. Half the cap
24
+ // leaves ample headroom for JSON envelope overhead.
25
+ const MAX_BATCH_BODY_BYTES = 32 * 1024 * 1024;
26
+ /**
27
+ * Split payloads into consecutive batches bounded by both count
28
+ * (`MAX_RULES_IMPORT_BATCH`) and approximate serialized size. A single
29
+ * payload larger than the byte budget still ships alone — the server's
30
+ * per-field caps are the authority on whether it is acceptable.
31
+ */
32
+ export function chunkRulePayloads(rules) {
33
+ const batches = [];
34
+ let batch = [];
35
+ let batchBytes = 0;
36
+ for (const rule of rules) {
37
+ // Real UTF-8 bytes, not string length — multi-byte content (CJK, Cyrillic)
38
+ // serializes up to 3x larger than its UTF-16 code-unit count, and the
39
+ // server cap this budget protects is a Content-Length byte cap.
40
+ const ruleBytes = Buffer.byteLength(JSON.stringify(rule), 'utf8');
41
+ if (batch.length > 0 &&
42
+ (batch.length >= MAX_RULES_IMPORT_BATCH ||
43
+ batchBytes + ruleBytes > MAX_BATCH_BODY_BYTES)) {
44
+ batches.push(batch);
45
+ batch = [];
46
+ batchBytes = 0;
47
+ }
48
+ batch.push(rule);
49
+ batchBytes += ruleBytes;
50
+ }
51
+ if (batch.length > 0)
52
+ batches.push(batch);
53
+ return batches;
54
+ }
55
+ /**
56
+ * POST `RawGuideFilePayload`s to the dashboard import endpoint, chunked to
57
+ * stay under the server's `MAX_RULES_IMPORT_BATCH` per-request cap and its
58
+ * request-body byte cap, and sum the parsed results. Throws on transport
59
+ * errors, non-2xx responses, or malformed bodies. Empty `rules` is rejected
60
+ * here so the CLI never sends a useless request.
61
+ */
62
+ export async function importRules(options) {
63
+ if (options.rules.length === 0) {
64
+ throw new Error('importRules: rules array must not be empty');
65
+ }
66
+ const fetchImpl = options.fetchImpl ?? fetch;
67
+ const url = `${trimTrailingSlashes(options.dashboardUrl)}/api/rules/import`;
68
+ let imported = 0;
69
+ let skipped = 0;
70
+ let members;
71
+ for (const batch of chunkRulePayloads(options.rules)) {
72
+ const response = await fetchImpl(url, {
73
+ method: 'POST',
74
+ headers: {
75
+ Authorization: `Bearer ${options.token}`,
76
+ 'Content-Type': 'application/json',
77
+ },
78
+ body: JSON.stringify({ rules: batch }),
79
+ });
80
+ if (!response.ok) {
81
+ const text = await response.text().catch(() => '');
82
+ throw new Error(`Import failed with ${response.status}${text ? `: ${text}` : ''}`);
83
+ }
84
+ const json = (await response.json());
85
+ const result = v.parse(ImportSuccessSchema, json);
86
+ imported += result.imported;
87
+ skipped += result.skipped;
88
+ if (result.members) {
89
+ members = members ?? { added: 0, updated: 0, removed: 0, unchanged: 0 };
90
+ members.added += result.members.added;
91
+ members.updated += result.members.updated;
92
+ members.removed += result.members.removed;
93
+ members.unchanged += result.members.unchanged;
94
+ }
95
+ }
96
+ return members ? { imported, skipped, members } : { imported, skipped };
97
+ }
98
+ //# sourceMappingURL=import-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-client.js","sourceRoot":"","sources":["../../src/rules/import-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { ExportPrompts, ExportRulesWithPullResult } from '../commands/rules/export.js';
2
+ import type { GuideFileFormat } from '@auden.to/protocol';
3
+ export type PullGuidesIntoRepoOptions = {
4
+ cwd: string;
5
+ dashboardUrl: string;
6
+ token: string;
7
+ /** Formats to restore. Defaults to all supported formats so a fresh repo
8
+ * gets the user's full setup back in whatever format each guide came from. */
9
+ formats?: ReadonlyArray<GuideFileFormat>;
10
+ /** Override the cached bundle path (defaults to ~/.auden/guides.json). */
11
+ bundlePath?: string;
12
+ /** Skip every confirmation, overwrites included. */
13
+ yes?: boolean;
14
+ /** Custom prompts (tests / non-stdin callers). Defaults to: NEW files
15
+ * auto-confirmed (the caller already asked), OVERWRITE per-file with diff. */
16
+ prompts?: ExportPrompts;
17
+ /** Apply ANSI colors when rendering overwrite diffs. */
18
+ color?: boolean;
19
+ fetchFn?: typeof fetch;
20
+ onPull?: (count: number, target: string) => void;
21
+ };
22
+ /**
23
+ * Pull the user's active guide bundle from the dashboard and write it into a
24
+ * repo — the cross-machine / fresh-repo restore path `auden init` offers so a
25
+ * brand-new project starts with the user's accumulated setup rather than cold.
26
+ *
27
+ * Always pulls a fresh bundle (mode 'always'): init runs once at setup time, so
28
+ * the local cache may be stale or absent. The caller is expected to have already
29
+ * confirmed intent ("pull your guides into this repo?"), so brand-new files are
30
+ * written without a second bulk confirm; existing files still get a per-file
31
+ * diff confirmation so re-running init never silently clobbers local edits.
32
+ */
33
+ export declare function pullGuidesIntoRepo(opts: PullGuidesIntoRepoOptions): Promise<ExportRulesWithPullResult>;
34
+ //# sourceMappingURL=init-pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-pull.d.ts","sourceRoot":"","sources":["../../src/rules/init-pull.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,aAAa,EAEb,yBAAyB,EAC1B,MAAM,6BAA6B,CAAA;AACpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEzD,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb;mFAC+E;IAC/E,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAA;IACxC,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,GAAG,CAAC,EAAE,OAAO,CAAA;IACb;mFAC+E;IAC/E,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,wDAAwD;IACxD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;IACtB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CACjD,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC,CA4BpC"}
@@ -0,0 +1,43 @@
1
+ import { AUDEN_GUIDES_FILE } from '../auden-paths.js';
2
+ import { ALL_FORMATS, makeStdinPrompts, runRulesExportWithPull, } from '../commands/rules/export.js';
3
+ import { BUNDLED_SKILLS } from '../skill-template.js';
4
+ /**
5
+ * Pull the user's active guide bundle from the dashboard and write it into a
6
+ * repo — the cross-machine / fresh-repo restore path `auden init` offers so a
7
+ * brand-new project starts with the user's accumulated setup rather than cold.
8
+ *
9
+ * Always pulls a fresh bundle (mode 'always'): init runs once at setup time, so
10
+ * the local cache may be stale or absent. The caller is expected to have already
11
+ * confirmed intent ("pull your guides into this repo?"), so brand-new files are
12
+ * written without a second bulk confirm; existing files still get a per-file
13
+ * diff confirmation so re-running init never silently clobbers local edits.
14
+ */
15
+ export async function pullGuidesIntoRepo(opts) {
16
+ const prompts = opts.prompts ?? {
17
+ ...makeStdinPrompts(),
18
+ confirmNewFiles: async () => true,
19
+ };
20
+ const exportArgs = {
21
+ cwd: opts.cwd,
22
+ format: opts.formats ?? ALL_FORMATS,
23
+ bundlePath: opts.bundlePath ?? AUDEN_GUIDES_FILE,
24
+ yes: opts.yes ?? false,
25
+ write: true,
26
+ color: opts.color ?? false,
27
+ prompts,
28
+ // init's own skill step just wrote (or deliberately kept) these — a stale
29
+ // dashboard copy imported on some other machine must not offer to clobber
30
+ // the fresh install one step later.
31
+ excludePathPrefixes: BUNDLED_SKILLS.map((skill) => `.claude/skills/${skill.name}/`),
32
+ pull: {
33
+ mode: 'always',
34
+ dashboardUrl: opts.dashboardUrl,
35
+ token: opts.token,
36
+ ...(opts.fetchFn ? { fetchFn: opts.fetchFn } : {}),
37
+ },
38
+ };
39
+ if (opts.onPull)
40
+ exportArgs.onPull = opts.onPull;
41
+ return runRulesExportWithPull(exportArgs);
42
+ }
43
+ //# sourceMappingURL=init-pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-pull.js","sourceRoot":"","sources":["../../src/rules/init-pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,6BAA6B,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AA6BrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAA+B;IAE/B,MAAM,OAAO,GAAkB,IAAI,CAAC,OAAO,IAAI;QAC7C,GAAG,gBAAgB,EAAE;QACrB,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI;KAClC,CAAA;IAED,MAAM,UAAU,GAA4B;QAC1C,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,MAAM,EAAE,IAAI,CAAC,OAAO,IAAI,WAAW;QACnC,UAAU,EAAE,IAAI,CAAC,UAAU,IAAI,iBAAiB;QAChD,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK;QACtB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK;QAC1B,OAAO;QACP,0EAA0E;QAC1E,0EAA0E;QAC1E,oCAAoC;QACpC,mBAAmB,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,KAAK,CAAC,IAAI,GAAG,CAAC;QACnF,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD;KACF,CAAA;IACD,IAAI,IAAI,CAAC,MAAM;QAAE,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAEhD,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAA;AAC3C,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { GuideMemberFile } from '@auden.to/protocol';
2
+ export type FetchGuideMemberFilesOptions = {
3
+ dashboardUrl: string;
4
+ token: string;
5
+ guideId: string;
6
+ /** Override fetch for tests. Defaults to globalThis.fetch. */
7
+ fetchImpl?: typeof fetch;
8
+ };
9
+ /**
10
+ * Fetch a skill guide's member files from the dashboard — the export
11
+ * round-trip's read side. Member bodies are deliberately not part of the
12
+ * cached guide bundle (the eval hot path pulls that every session), so this
13
+ * is a lazy per-guide call made only when exporting `skill-md` guides.
14
+ * Throws on transport errors, non-2xx responses, or malformed bodies.
15
+ */
16
+ export declare function fetchGuideMemberFiles(options: FetchGuideMemberFilesOptions): Promise<GuideMemberFile[]>;
17
+ //# sourceMappingURL=member-files-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-files-client.d.ts","sourceRoot":"","sources":["../../src/rules/member-files-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEzD,MAAM,MAAM,4BAA4B,GAAG;IACzC,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,8DAA8D;IAC9D,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,CAAA;AAED;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,eAAe,EAAE,CAAC,CAsB5B"}
@@ -0,0 +1,29 @@
1
+ import { parseGuideMemberFilesResponse } from '@auden.to/protocol';
2
+ /**
3
+ * Fetch a skill guide's member files from the dashboard — the export
4
+ * round-trip's read side. Member bodies are deliberately not part of the
5
+ * cached guide bundle (the eval hot path pulls that every session), so this
6
+ * is a lazy per-guide call made only when exporting `skill-md` guides.
7
+ * Throws on transport errors, non-2xx responses, or malformed bodies.
8
+ */
9
+ export async function fetchGuideMemberFiles(options) {
10
+ const fetchImpl = options.fetchImpl ?? fetch;
11
+ const base = options.dashboardUrl.replace(/\/+$/, '');
12
+ const url = `${base}/api/v1/guides/${encodeURIComponent(options.guideId)}/member-files`;
13
+ const response = await fetchImpl(url, {
14
+ headers: { Authorization: `Bearer ${options.token}` },
15
+ });
16
+ if (!response.ok) {
17
+ const detail = await response.text().catch(() => '');
18
+ throw new Error(`Member-file fetch failed with ${response.status}${detail ? `: ${detail}` : ''}`);
19
+ }
20
+ let payload;
21
+ try {
22
+ payload = await response.json();
23
+ }
24
+ catch {
25
+ throw new Error('Member-file response was not valid JSON.');
26
+ }
27
+ return parseGuideMemberFilesResponse(payload).memberFiles;
28
+ }
29
+ //# sourceMappingURL=member-files-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"member-files-client.js","sourceRoot":"","sources":["../../src/rules/member-files-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,oBAAoB,CAAA;AAYlE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAA;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACrD,MAAM,GAAG,GAAG,GAAG,IAAI,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAA;IAEvF,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QACpC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,EAAE;KACtD,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACpD,MAAM,IAAI,KAAK,CACb,iCAAiC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjF,CAAA;IACH,CAAC;IAED,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,6BAA6B,CAAC,OAAO,CAAC,CAAC,WAAW,CAAA;AAC3D,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Return true if `child` is strictly contained within `parent` — i.e. equal or
3
+ * a descendant. Uses `path.relative` so `/repo` does not contain
4
+ * `/repo-malicious` (a prefix-match bug we hit on the first pass). An absolute
5
+ * result from `relative` means the two roots live on different Windows drives —
6
+ * definitely not contained.
7
+ */
8
+ export declare function isPathWithin(parent: string, child: string): boolean;
9
+ //# sourceMappingURL=path-contains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-contains.d.ts","sourceRoot":"","sources":["../../src/rules/path-contains.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAKzD"}
@@ -0,0 +1,17 @@
1
+ import { relative } from 'node:path';
2
+ /**
3
+ * Return true if `child` is strictly contained within `parent` — i.e. equal or
4
+ * a descendant. Uses `path.relative` so `/repo` does not contain
5
+ * `/repo-malicious` (a prefix-match bug we hit on the first pass). An absolute
6
+ * result from `relative` means the two roots live on different Windows drives —
7
+ * definitely not contained.
8
+ */
9
+ export function isPathWithin(parent, child) {
10
+ const rel = relative(parent, child);
11
+ if (rel === '')
12
+ return true;
13
+ if (rel.startsWith('..'))
14
+ return false;
15
+ return !/^[a-zA-Z]:[/\\]/.test(rel) && !rel.startsWith('/');
16
+ }
17
+ //# sourceMappingURL=path-contains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-contains.js","sourceRoot":"","sources":["../../src/rules/path-contains.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAEpC;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,KAAa;IACxD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACnC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAC3B,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IACtC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC7D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type RawGuideFilePayload } from '@auden.to/protocol';
2
+ import type { DiscoveredGuideFile } from './discover.js';
3
+ /**
4
+ * Convert a discovered guide file into the canonical `RawGuideFilePayload`
5
+ * shape accepted by `POST /api/rules/import`. Throws if the resulting payload
6
+ * fails schema validation — a CLI bug, not a user error.
7
+ *
8
+ * Skill member files ride along only when discovery scanned the skill
9
+ * directory (`members` set, possibly `[]`); a payload without the field
10
+ * leaves the server's member rows untouched.
11
+ */
12
+ export declare function buildRulePayload(file: DiscoveredGuideFile): RawGuideFilePayload;
13
+ //# sourceMappingURL=payload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/rules/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAEvF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,mBAAmB,CAuB/E"}
@@ -0,0 +1,35 @@
1
+ import { parseRawGuideFilePayload } from '@auden.to/protocol';
2
+ /**
3
+ * Convert a discovered guide file into the canonical `RawGuideFilePayload`
4
+ * shape accepted by `POST /api/rules/import`. Throws if the resulting payload
5
+ * fails schema validation — a CLI bug, not a user error.
6
+ *
7
+ * Skill member files ride along only when discovery scanned the skill
8
+ * directory (`members` set, possibly `[]`); a payload without the field
9
+ * leaves the server's member rows untouched.
10
+ */
11
+ export function buildRulePayload(file) {
12
+ return parseRawGuideFilePayload({
13
+ path: file.payloadPath,
14
+ format: file.format,
15
+ rawContent: file.rawContent,
16
+ lastModified: file.lastModified,
17
+ content_hash: file.contentHash,
18
+ ...(file.members
19
+ ? {
20
+ members: file.members.map((member) => ({
21
+ path: member.path,
22
+ rawContent: member.rawContent,
23
+ lastModified: member.lastModified,
24
+ content_hash: member.contentHash,
25
+ })),
26
+ // Skipped-but-present files ride along so the server preserves
27
+ // their rows instead of reading absence as removal.
28
+ ...(file.membersSkippedPaths?.length
29
+ ? { skippedMemberPaths: file.membersSkippedPaths }
30
+ : {}),
31
+ }
32
+ : {}),
33
+ });
34
+ }
35
+ //# sourceMappingURL=payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/rules/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAA4B,MAAM,oBAAoB,CAAA;AAIvF;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,OAAO,wBAAwB,CAAC;QAC9B,IAAI,EAAE,IAAI,CAAC,WAAW;QACtB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,YAAY,EAAE,IAAI,CAAC,WAAW;QAC9B,GAAG,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;oBACrC,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,YAAY,EAAE,MAAM,CAAC,YAAY;oBACjC,YAAY,EAAE,MAAM,CAAC,WAAW;iBACjC,CAAC,CAAC;gBACH,+DAA+D;gBAC/D,oDAAoD;gBACpD,GAAG,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM;oBAClC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,CAAC,mBAAmB,EAAE;oBAClD,CAAC,CAAC,EAAE,CAAC;aACR;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { GuideBundleResponse } from '@auden.to/protocol';
2
+ export type PullGuideBundleOptions = {
3
+ dashboardUrl: string;
4
+ token: string;
5
+ bundlePath: string;
6
+ fetchFn?: typeof fetch;
7
+ };
8
+ export type PullGuideBundleResult = {
9
+ bundle: GuideBundleResponse;
10
+ bundlePath: string;
11
+ };
12
+ export declare function pullGuideBundle(opts: PullGuideBundleOptions): Promise<PullGuideBundleResult>;
13
+ //# sourceMappingURL=pull-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull-bundle.d.ts","sourceRoot":"","sources":["../../src/rules/pull-bundle.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAE7D,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,mBAAmB,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CAiChC"}
@@ -0,0 +1,32 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
+ import { parseGuideBundleResponse } from '@auden.to/protocol';
4
+ export async function pullGuideBundle(opts) {
5
+ const fetchFn = opts.fetchFn ?? fetch;
6
+ const url = `${opts.dashboardUrl.replace(/\/+$/, '')}/api/v1/guides`;
7
+ const response = await fetchFn(url, {
8
+ headers: { Authorization: `Bearer ${opts.token}` },
9
+ });
10
+ if (!response.ok) {
11
+ const detail = await response.text().catch(() => '');
12
+ throw new Error(`Guide pull failed with ${response.status}${detail ? `: ${detail}` : ''}`);
13
+ }
14
+ let payload;
15
+ try {
16
+ payload = await response.json();
17
+ }
18
+ catch {
19
+ throw new Error('Guide bundle response was not valid JSON.');
20
+ }
21
+ let bundle;
22
+ try {
23
+ bundle = parseGuideBundleResponse(payload);
24
+ }
25
+ catch {
26
+ throw new Error('Guide bundle response was malformed.');
27
+ }
28
+ await mkdir(dirname(opts.bundlePath), { recursive: true });
29
+ await writeFile(opts.bundlePath, JSON.stringify(bundle, null, 2) + '\n');
30
+ return { bundle, bundlePath: opts.bundlePath };
31
+ }
32
+ //# sourceMappingURL=pull-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull-bundle.js","sourceRoot":"","sources":["../../src/rules/pull-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAgB7D,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAA;IACrC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,gBAAgB,CAAA;IAEpE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAClC,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE;KACnD,CAAC,CAAA;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;QACpD,MAAM,IAAI,KAAK,CACb,0BAA0B,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1E,CAAA;IACH,CAAC;IAED,IAAI,OAAgB,CAAA;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAA;IAC9D,CAAC;IAED,IAAI,MAA2B,CAAA;IAC/B,IAAI,CAAC;QACH,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAExE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAA;AAChD,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { rescanSkill, type DiscoveredGuideFile } from './discover.js';
2
+ import type { RawGuideFileDeletion, RawGuideFilePayload } from '@auden.to/protocol';
3
+ export type WatchEventKind = 'change' | 'rename';
4
+ export type WatchEvent = {
5
+ kind: WatchEventKind;
6
+ /** Absolute path of the affected file. */
7
+ absolutePath: string;
8
+ /** Path relative to the discovery root that owns the watcher. */
9
+ payloadPath: string;
10
+ /** Display path shown to the user. */
11
+ displayPath: string;
12
+ };
13
+ export type WatchEventSource = {
14
+ /**
15
+ * Start emitting events. Returns a stop function used to tear watchers down.
16
+ * Implementations must call `onEvent` for every change/rename event seen on
17
+ * the project-level and (optional) global discovery roots.
18
+ */
19
+ start(onEvent: (event: WatchEvent) => void): () => Promise<void>;
20
+ };
21
+ export type WatchEngineOptions = {
22
+ cwd: string;
23
+ /** Pre-discovered files used to seed the in-memory state (hash + paths). */
24
+ initial: DiscoveredGuideFile[];
25
+ /**
26
+ * Roots whose descendant paths the engine will accept. Events outside these
27
+ * roots are dropped unless the path is already tracked from the initial
28
+ * scan. Defaults to `[cwd]`. The CLI passes `[cwd, ~/.claude]` when
29
+ * `--global` is enabled so newly-created global guide files are picked up.
30
+ */
31
+ allowedRoots?: string[];
32
+ source: WatchEventSource;
33
+ /** Coalesce burst events for the same path within this window (ms). */
34
+ debounceMs: number;
35
+ /**
36
+ * Confirm a missing file is really gone before reporting a deletion. Editors
37
+ * often write atomically by deleting then recreating; the stability window
38
+ * suppresses that as a deletion and lets the follow-on change event fire.
39
+ */
40
+ deleteStabilityMs: number;
41
+ /** Send a deletion batch to the dashboard. Required at runtime. */
42
+ sendDeletions?: (deletions: RawGuideFileDeletion[]) => Promise<void>;
43
+ /** Send a payload batch to the dashboard. Required at runtime. */
44
+ sendImports?: (payloads: RawGuideFilePayload[]) => Promise<void>;
45
+ /** Log line callback — defaults to console.log. */
46
+ log?: (line: string) => void;
47
+ /** Override file read for tests. */
48
+ readFileImpl?: (absolutePath: string) => Promise<{
49
+ rawContent: string;
50
+ lastModified: number;
51
+ } | null>;
52
+ /** Override the per-skill directory re-scan for tests. */
53
+ rescanSkillImpl?: typeof rescanSkill;
54
+ };
55
+ /**
56
+ * Stateful engine that turns raw fs events into batched import/delete calls.
57
+ * Exposed so tests can drive it deterministically.
58
+ *
59
+ * Per-path debouncing collapses editor save bursts. A deletion is only
60
+ * reported after `deleteStabilityMs` confirms the file is still gone — this
61
+ * lets atomic delete-then-create saves resolve as a change instead.
62
+ */
63
+ export declare class RuleWatchEngine {
64
+ private readonly allowedRoots;
65
+ private readonly source;
66
+ private readonly debounceMs;
67
+ private readonly deleteStabilityMs;
68
+ private readonly sendImports;
69
+ private readonly sendDeletions;
70
+ private readonly log;
71
+ private readonly readFileImpl;
72
+ private readonly rescanSkillImpl;
73
+ private readonly known;
74
+ private readonly pending;
75
+ private readonly deletionTimers;
76
+ private readonly skillChains;
77
+ private stop;
78
+ private stopped;
79
+ constructor(options: WatchEngineOptions);
80
+ start(): void;
81
+ shutdown(): Promise<void>;
82
+ /** @internal — test helper to drive an event without going through the source. */
83
+ injectEvent(event: WatchEvent): void;
84
+ /** @internal — test helper to flush a pending debounce immediately. */
85
+ flush(absolutePath: string): Promise<void>;
86
+ private onEvent;
87
+ private process;
88
+ /**
89
+ * Find the tracked SKILL.md whose directory most tightly contains
90
+ * `absolutePath` — the skill a changed member file belongs to. Longest
91
+ * match wins so a nested skill owns its own subtree.
92
+ */
93
+ private findOwningSkill;
94
+ /**
95
+ * Re-scan a skill's directory and re-send its SKILL.md payload with a fresh
96
+ * members array, serialized per owning skill. The server treats that array as
97
+ * the complete member set, so a member (or SKILL.md) add/edit/delete
98
+ * propagates by re-sending the whole skill. Chaining on `skillChains` keeps
99
+ * two near-simultaneous events for the same skill from POSTing concurrently —
100
+ * an earlier, staler snapshot must not land after a newer one and revert it.
101
+ */
102
+ private resyncSkill;
103
+ private doResyncSkill;
104
+ private scheduleDeletion;
105
+ private fireDeletion;
106
+ }
107
+ type FsWatcher = {
108
+ close(): void;
109
+ };
110
+ export type CreateFsSourceOptions = {
111
+ cwd: string;
112
+ global: boolean;
113
+ homedir?: string;
114
+ /** Underlying watch primitive. Defaults to node:fs.watch. */
115
+ watchImpl?: (path: string, options: {
116
+ recursive?: boolean;
117
+ }, listener: (eventType: string, filename: string | null) => void) => FsWatcher;
118
+ };
119
+ export declare function createFsWatchSource(options: CreateFsSourceOptions): WatchEventSource;
120
+ export {};
121
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/rules/watch.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAIrE,OAAO,KAAK,EAEV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,oBAAoB,CAAA;AAM3B,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEhD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,cAAc,CAAA;IACpB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACjE,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,4EAA4E;IAC5E,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,MAAM,EAAE,gBAAgB,CAAA;IACxB,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAA;IACzB,mEAAmE;IACnE,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,oBAAoB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpE,kEAAkE;IAClE,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,mBAAmB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,mDAAmD;IACnD,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,oCAAoC;IACpC,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;QAC/C,UAAU,EAAE,MAAM,CAAA;QAClB,YAAY,EAAE,MAAM,CAAA;KACrB,GAAG,IAAI,CAAC,CAAA;IACT,0DAA0D;IAC1D,eAAe,CAAC,EAAE,OAAO,WAAW,CAAA;CACrC,CAAA;AAwDD;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoD;IAChF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsD;IACpF,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAwB;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiD;IAC9E,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IAEpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmD;IAI3E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmD;IAKlF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmC;IAC/D,OAAO,CAAC,IAAI,CAAqC;IACjD,OAAO,CAAC,OAAO,CAAQ;gBAEX,OAAO,EAAE,kBAAkB;IAoCvC,KAAK,IAAI,IAAI;IAKP,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAe/B,kFAAkF;IAClF,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAIpC,uEAAuE;IACjE,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhD,OAAO,CAAC,OAAO;YA4BD,OAAO;IAsGrB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAcvB;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;YAYL,aAAa;IAmC3B,OAAO,CAAC,gBAAgB;YAyBV,YAAY;CAkB3B;AAMD,KAAK,SAAS,GAAG;IACf,KAAK,IAAI,IAAI,CAAA;CACd,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,EAChC,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,KAC3D,SAAS,CAAA;CACf,CAAA;AAYD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,gBAAgB,CA8EpF"}