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,200 @@
1
+ import { readFile, readdir } from 'node:fs/promises';
2
+ import { basename, dirname, extname, join } from 'node:path';
3
+ import { inferProviderFromModel } from './providers.js';
4
+ /** Same SKILL.md identification idiom as `rules/discover.ts`'s `isSkillMd`. */
5
+ function isSkillMdPath(path) {
6
+ return basename(path).toLowerCase() === 'skill.md';
7
+ }
8
+ function asRecord(value) {
9
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
10
+ return null;
11
+ }
12
+ return value;
13
+ }
14
+ /**
15
+ * Detects a skill-load signal in one assistant message's content blocks
16
+ * (docs/plans/token-cost-tracking-plan.md §13.2): either an explicit `Skill`
17
+ * tool_use (input.skill names the skill), or a file-read tool_use whose path
18
+ * targets a `SKILL.md` (skill name = its parent directory). Only the first
19
+ * signal in a message is used — a message that requests two skill loads at
20
+ * once is a rare edge case not worth the double-counting risk of attributing
21
+ * the next message's usage to both.
22
+ */
23
+ function detectSkillLoadSignal(message) {
24
+ const content = message.content;
25
+ if (!Array.isArray(content)) {
26
+ return null;
27
+ }
28
+ for (const block of content) {
29
+ const blockRecord = asRecord(block);
30
+ if (!blockRecord || blockRecord.type !== 'tool_use') {
31
+ continue;
32
+ }
33
+ const toolName = typeof blockRecord.name === 'string' ? blockRecord.name : null;
34
+ const input = asRecord(blockRecord.input);
35
+ if (toolName === 'Skill') {
36
+ const skillName = typeof input?.skill === 'string' ? input.skill : null;
37
+ if (skillName) {
38
+ return skillName;
39
+ }
40
+ continue;
41
+ }
42
+ const path = typeof input?.file_path === 'string'
43
+ ? input.file_path
44
+ : typeof input?.path === 'string'
45
+ ? input.path
46
+ : null;
47
+ if (path && isSkillMdPath(path)) {
48
+ return basename(dirname(path));
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ function toNonNegativeInt(value) {
54
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0
55
+ ? Math.floor(value)
56
+ : 0;
57
+ }
58
+ async function collectJsonlFiles(dir) {
59
+ const entries = await readdir(dir, { withFileTypes: true });
60
+ const files = await Promise.all(entries.map(async (entry) => {
61
+ const fullPath = join(dir, entry.name);
62
+ if (entry.isDirectory()) {
63
+ return collectJsonlFiles(fullPath);
64
+ }
65
+ return extname(entry.name) === '.jsonl' ? [fullPath] : [];
66
+ }));
67
+ return files.flat().sort();
68
+ }
69
+ async function readJsonlRecords(path) {
70
+ const raw = await readFile(path, 'utf8');
71
+ return raw
72
+ .split('\n')
73
+ .map((line) => line.trim())
74
+ .filter(Boolean)
75
+ .flatMap((line) => {
76
+ try {
77
+ return [JSON.parse(line)];
78
+ }
79
+ catch {
80
+ return [];
81
+ }
82
+ });
83
+ }
84
+ /**
85
+ * Extracts per-session, per-model token usage from Claude Code JSONL
86
+ * transcripts (docs/plans/token-cost-tracking-plan.md §5.1), plus per-skill
87
+ * Tier-1 "load overhead" usage (§13.3): when an assistant message requests a
88
+ * `Skill` tool or reads a `SKILL.md`, the *next* assistant message's usage is
89
+ * the first-load cost of that skill (v1 approximation — see §13.3's caching
90
+ * nuance). Reads only `usage`/`model`/`sessionId` and tool_use `name`/`input`
91
+ * off assistant messages — never message text.
92
+ *
93
+ * Each message carries its own (non-cumulative) usage, so we sum every
94
+ * assistant message's usage per (session, model). Messages are deduped by
95
+ * their id so re-reading a transcript that grew since the last sync does not
96
+ * double-count lines already summed.
97
+ */
98
+ export async function extractRunUsage(options) {
99
+ if (!options?.transcriptsDir) {
100
+ return { runUsage: [], skillUsage: [] };
101
+ }
102
+ const files = await collectJsonlFiles(options.transcriptsDir).catch(() => []);
103
+ const sessionUsage = new Map();
104
+ const sessionSkillUsage = new Map();
105
+ const pendingSkillLoads = new Map();
106
+ const seenMessageIds = new Set();
107
+ for (const file of files) {
108
+ const fallbackSessionId = basename(file, extname(file));
109
+ const records = await readJsonlRecords(file);
110
+ for (const recordValue of records) {
111
+ const record = asRecord(recordValue);
112
+ if (!record || record.type !== 'assistant') {
113
+ continue;
114
+ }
115
+ const message = asRecord(record.message);
116
+ if (!message) {
117
+ continue;
118
+ }
119
+ const usage = asRecord(message.usage);
120
+ if (!usage) {
121
+ continue;
122
+ }
123
+ const model = typeof message.model === 'string' ? message.model : null;
124
+ if (!model) {
125
+ continue;
126
+ }
127
+ const messageId = typeof message.id === 'string'
128
+ ? message.id
129
+ : typeof record.uuid === 'string'
130
+ ? record.uuid
131
+ : null;
132
+ if (messageId) {
133
+ if (seenMessageIds.has(messageId)) {
134
+ continue;
135
+ }
136
+ seenMessageIds.add(messageId);
137
+ }
138
+ const sessionId = typeof record.sessionId === 'string' && record.sessionId.length > 0
139
+ ? record.sessionId
140
+ : fallbackSessionId;
141
+ const modelMap = sessionUsage.get(sessionId) ?? new Map();
142
+ sessionUsage.set(sessionId, modelMap);
143
+ const existing = modelMap.get(model) ?? {
144
+ model,
145
+ provider: inferProviderFromModel(model),
146
+ inputTokens: 0,
147
+ outputTokens: 0,
148
+ cacheReadTokens: 0,
149
+ cacheWriteTokens: 0,
150
+ };
151
+ modelMap.set(model, {
152
+ ...existing,
153
+ inputTokens: existing.inputTokens + toNonNegativeInt(usage.input_tokens),
154
+ outputTokens: existing.outputTokens + toNonNegativeInt(usage.output_tokens),
155
+ cacheReadTokens: (existing.cacheReadTokens ?? 0) +
156
+ toNonNegativeInt(usage.cache_read_input_tokens),
157
+ cacheWriteTokens: (existing.cacheWriteTokens ?? 0) +
158
+ toNonNegativeInt(usage.cache_creation_input_tokens),
159
+ });
160
+ // Attribute this message's usage to a skill load requested by the
161
+ // *previous* assistant message, if any — this message is the first turn
162
+ // to see that skill's content in context. Must run before detecting a
163
+ // new signal below, so a message that both closes one load and opens
164
+ // another handles both correctly.
165
+ const pendingSkillName = pendingSkillLoads.get(sessionId);
166
+ if (pendingSkillName) {
167
+ pendingSkillLoads.delete(sessionId);
168
+ const skillMap = sessionSkillUsage.get(sessionId) ?? new Map();
169
+ sessionSkillUsage.set(sessionId, skillMap);
170
+ const skillKey = `${pendingSkillName}::${model}`;
171
+ const existingSkillUsage = skillMap.get(skillKey) ?? {
172
+ skillName: pendingSkillName,
173
+ model,
174
+ inputTokens: 0,
175
+ cacheWriteTokens: 0,
176
+ };
177
+ skillMap.set(skillKey, {
178
+ ...existingSkillUsage,
179
+ inputTokens: existingSkillUsage.inputTokens + toNonNegativeInt(usage.input_tokens),
180
+ cacheWriteTokens: (existingSkillUsage.cacheWriteTokens ?? 0) +
181
+ toNonNegativeInt(usage.cache_creation_input_tokens),
182
+ });
183
+ }
184
+ const skillLoadSignal = detectSkillLoadSignal(message);
185
+ if (skillLoadSignal) {
186
+ pendingSkillLoads.set(sessionId, skillLoadSignal);
187
+ }
188
+ }
189
+ }
190
+ const runUsage = Array.from(sessionUsage.entries()).map(([sessionId, modelMap]) => ({
191
+ sessionId,
192
+ usage: Array.from(modelMap.values()),
193
+ }));
194
+ const skillUsage = Array.from(sessionSkillUsage.entries()).map(([sessionId, skillMap]) => ({
195
+ sessionId,
196
+ usage: Array.from(skillMap.values()),
197
+ }));
198
+ return { runUsage, skillUsage };
199
+ }
200
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/usage/extract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Infers a model's API provider from its id prefix
3
+ * (docs/plans/token-cost-tracking-plan.md §8: "derive `provider` from model id
4
+ * prefix when the transcript doesn't state it"). Returns `undefined` rather
5
+ * than guessing wrong for an id we don't recognize.
6
+ */
7
+ export declare function inferProviderFromModel(model: string): string | undefined;
8
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/usage/providers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAiBxE"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Infers a model's API provider from its id prefix
3
+ * (docs/plans/token-cost-tracking-plan.md §8: "derive `provider` from model id
4
+ * prefix when the transcript doesn't state it"). Returns `undefined` rather
5
+ * than guessing wrong for an id we don't recognize.
6
+ */
7
+ export function inferProviderFromModel(model) {
8
+ if (model.startsWith('claude-') || model.startsWith('anthropic/')) {
9
+ return 'anthropic';
10
+ }
11
+ if (model.startsWith('gpt-') ||
12
+ model.startsWith('o1-') ||
13
+ model.startsWith('o3-') ||
14
+ model.startsWith('o4-') ||
15
+ model.startsWith('openai/')) {
16
+ return 'openai';
17
+ }
18
+ if (model.startsWith('gemini-') || model.startsWith('google/')) {
19
+ return 'google';
20
+ }
21
+ return undefined;
22
+ }
23
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/usage/providers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAClE,OAAO,WAAW,CAAA;IACpB,CAAC;IACD,IACE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;QACxB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QACvB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QACvB,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QACvB,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAC3B,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/D,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { DashboardSyncAction } from '@auden.to/protocol';
2
+ export type VerdictQueueResult = {
3
+ actions: DashboardSyncAction[];
4
+ filePaths: string[];
5
+ /**
6
+ * Files that were read in full but whose content is not a valid queued
7
+ * verdict (bad JSON or failing schema). They will never become valid, so the
8
+ * caller deletes them instead of re-warning about them on every run. Files
9
+ * that only failed to read (transient I/O, permissions) are omitted — they
10
+ * are left in place to retry next time.
11
+ */
12
+ invalidFilePaths: string[];
13
+ };
14
+ /**
15
+ * Read all valid queued verdict files from `dir`.
16
+ * Returns the mapped sync actions, the absolute paths of the files that
17
+ * produced them (so the caller can delete them after a successful sync), and
18
+ * the paths of files whose content is permanently invalid (so the caller can
19
+ * clean them up instead of re-warning about them on every run).
20
+ */
21
+ export declare function readVerdictQueue(dir: string): Promise<VerdictQueueResult>;
22
+ /**
23
+ * Hard cap on pending queued verdicts. Bounds disk growth if the dashboard is
24
+ * unreachable for a long stretch — nothing else limited how many `auden
25
+ * verdict record` calls could pile up in `~/.auden/queue` while an outage
26
+ * lasts. Past the cap, the oldest entries are evicted to make room for new
27
+ * ones: a long enough outage loses old verdicts rather than filling the disk.
28
+ */
29
+ export declare const MAX_QUEUED_VERDICTS = 5000;
30
+ export type EnforceQueueCapResult = {
31
+ /** Number of oldest queue files deleted to get back under the cap. */
32
+ evicted: number;
33
+ };
34
+ /**
35
+ * Trim `dir` down to `maxEntries` queued verdict files. No-op when the
36
+ * directory is missing or already within the cap — that check is a cheap
37
+ * `readdir` with no file reads, since it runs on every `auden verdict
38
+ * record` call and the common case is nowhere near the cap.
39
+ *
40
+ * Once over the cap, permanently-invalid entries (bad JSON or failing
41
+ * schema — the same classification `readVerdictQueue` uses) are evicted
42
+ * first regardless of age: they can never be synced, so deleting them costs
43
+ * nothing, whereas evicting a still-syncable verdict is real data loss.
44
+ * Only once invalid entries are exhausted does eviction fall back to the
45
+ * oldest valid verdicts (by file mtime). Best-effort throughout: a file that
46
+ * fails to delete is left in place rather than throwing — eviction is
47
+ * housekeeping, not the operation the caller is actually trying to perform.
48
+ */
49
+ export declare function enforceVerdictQueueCap(dir: string, maxEntries?: number): Promise<EnforceQueueCapResult>;
50
+ //# sourceMappingURL=verdict-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict-queue.d.ts","sourceRoot":"","sources":["../src/verdict-queue.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAc7D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB;;;;;;OAMG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B,CAAA;AAaD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgD/E;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,MAAM,MAAM,qBAAqB,GAAG;IAClC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,UAAU,GAAE,MAA4B,GACvC,OAAO,CAAC,qBAAqB,CAAC,CAsChC"}
@@ -0,0 +1,131 @@
1
+ import { readFile, readdir, stat, unlink } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { VerdictSchema } from '@auden.to/protocol';
4
+ import * as v from 'valibot';
5
+ const QueuedVerdictSchema = v.object({
6
+ id: v.string(),
7
+ sessionId: v.string(),
8
+ actionType: v.string(),
9
+ summary: v.string(),
10
+ verdict: VerdictSchema,
11
+ timestamp: v.string(),
12
+ });
13
+ function toSyncAction(entry) {
14
+ return {
15
+ id: entry.id,
16
+ sessionId: entry.sessionId,
17
+ actionType: entry.actionType,
18
+ summary: entry.summary,
19
+ verdict: entry.verdict,
20
+ metadata: { recordedAt: entry.timestamp },
21
+ };
22
+ }
23
+ /**
24
+ * Read all valid queued verdict files from `dir`.
25
+ * Returns the mapped sync actions, the absolute paths of the files that
26
+ * produced them (so the caller can delete them after a successful sync), and
27
+ * the paths of files whose content is permanently invalid (so the caller can
28
+ * clean them up instead of re-warning about them on every run).
29
+ */
30
+ export async function readVerdictQueue(dir) {
31
+ const actions = [];
32
+ const filePaths = [];
33
+ const invalidFilePaths = [];
34
+ let entries;
35
+ try {
36
+ entries = await readdir(dir, { withFileTypes: true, encoding: 'utf8' });
37
+ }
38
+ catch {
39
+ return { actions, filePaths, invalidFilePaths };
40
+ }
41
+ const jsonFiles = entries.filter((d) => d.isFile() && d.name.endsWith('.json'));
42
+ for (const dirent of jsonFiles) {
43
+ // dirent.parentPath was added in Node 21.4; dirent.path is the equivalent
44
+ // property available in Node 20. Fall back to dir as a safety net.
45
+ const absPath = resolve(dirent.parentPath ?? dirent.path ?? dir, dirent.name);
46
+ let raw;
47
+ try {
48
+ raw = await readFile(absPath, 'utf8');
49
+ }
50
+ catch (err) {
51
+ // ENOENT is a harmless readdir/read race (the file was removed between
52
+ // the listing and the read) — stay silent and retry next run. Any other
53
+ // read failure (permissions, I/O) is a real queue file we can neither
54
+ // sync nor safely delete, so surface it rather than black-holing it: it
55
+ // would otherwise show as neither pending nor invalid anywhere.
56
+ if (err?.code !== 'ENOENT') {
57
+ console.warn(` warning: could not read queue file ${absPath}: ${err?.message}`);
58
+ }
59
+ continue;
60
+ }
61
+ try {
62
+ const parsed = v.parse(QueuedVerdictSchema, JSON.parse(raw));
63
+ actions.push(toSyncAction(parsed));
64
+ filePaths.push(absPath);
65
+ }
66
+ catch {
67
+ // Read in full but the content is not a valid queued verdict — it will
68
+ // never become valid, so mark it for cleanup by the caller.
69
+ invalidFilePaths.push(absPath);
70
+ }
71
+ }
72
+ return { actions, filePaths, invalidFilePaths };
73
+ }
74
+ /**
75
+ * Hard cap on pending queued verdicts. Bounds disk growth if the dashboard is
76
+ * unreachable for a long stretch — nothing else limited how many `auden
77
+ * verdict record` calls could pile up in `~/.auden/queue` while an outage
78
+ * lasts. Past the cap, the oldest entries are evicted to make room for new
79
+ * ones: a long enough outage loses old verdicts rather than filling the disk.
80
+ */
81
+ export const MAX_QUEUED_VERDICTS = 5000;
82
+ /**
83
+ * Trim `dir` down to `maxEntries` queued verdict files. No-op when the
84
+ * directory is missing or already within the cap — that check is a cheap
85
+ * `readdir` with no file reads, since it runs on every `auden verdict
86
+ * record` call and the common case is nowhere near the cap.
87
+ *
88
+ * Once over the cap, permanently-invalid entries (bad JSON or failing
89
+ * schema — the same classification `readVerdictQueue` uses) are evicted
90
+ * first regardless of age: they can never be synced, so deleting them costs
91
+ * nothing, whereas evicting a still-syncable verdict is real data loss.
92
+ * Only once invalid entries are exhausted does eviction fall back to the
93
+ * oldest valid verdicts (by file mtime). Best-effort throughout: a file that
94
+ * fails to delete is left in place rather than throwing — eviction is
95
+ * housekeeping, not the operation the caller is actually trying to perform.
96
+ */
97
+ export async function enforceVerdictQueueCap(dir, maxEntries = MAX_QUEUED_VERDICTS) {
98
+ let entries;
99
+ try {
100
+ entries = await readdir(dir, { withFileTypes: true, encoding: 'utf8' });
101
+ }
102
+ catch {
103
+ return { evicted: 0 };
104
+ }
105
+ const jsonFiles = entries.filter((d) => d.isFile() && d.name.endsWith('.json'));
106
+ if (jsonFiles.length <= maxEntries)
107
+ return { evicted: 0 };
108
+ const { filePaths: validPaths, invalidFilePaths } = await readVerdictQueue(dir);
109
+ let overflow = validPaths.length + invalidFilePaths.length - maxEntries;
110
+ if (overflow <= 0)
111
+ return { evicted: 0 };
112
+ let evicted = 0;
113
+ const invalidToEvict = invalidFilePaths.slice(0, overflow);
114
+ if (invalidToEvict.length > 0) {
115
+ const results = await Promise.allSettled(invalidToEvict.map((p) => unlink(p)));
116
+ evicted += results.filter((r) => r.status === 'fulfilled').length;
117
+ overflow -= invalidToEvict.length;
118
+ }
119
+ if (overflow > 0) {
120
+ const withMtime = await Promise.all(validPaths.map(async (absPath) => {
121
+ const info = await stat(absPath).catch(() => null);
122
+ return { absPath, mtimeMs: info?.mtimeMs ?? 0 };
123
+ }));
124
+ withMtime.sort((a, b) => a.mtimeMs - b.mtimeMs);
125
+ const validToEvict = withMtime.slice(0, overflow);
126
+ const results = await Promise.allSettled(validToEvict.map((f) => unlink(f.absPath)));
127
+ evicted += results.filter((r) => r.status === 'fulfilled').length;
128
+ }
129
+ return { evicted };
130
+ }
131
+ //# sourceMappingURL=verdict-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict-queue.js","sourceRoot":"","sources":["../src/verdict-queue.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "auden",
3
+ "version": "0.1.0-alpha.2",
4
+ "private": false,
5
+ "description": "Local-first CLI for Auden — evaluates AI coding agent actions against your guides on-device and syncs verdicts to your dashboard.",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "auden": "./dist/bin.js"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "import": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "!dist/.tsbuildinfo",
22
+ "README.md",
23
+ "LICENSE"
24
+ ],
25
+ "engines": {
26
+ "node": ">=20"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/auden-to/auden.git",
31
+ "directory": "packages/cli"
32
+ },
33
+ "homepage": "https://app.auden.to",
34
+ "keywords": [
35
+ "ai",
36
+ "agents",
37
+ "claude-code",
38
+ "agent-guidance",
39
+ "evaluation",
40
+ "cli"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public",
44
+ "provenance": false
45
+ },
46
+ "scripts": {
47
+ "build": "tsc --project tsconfig.json && node -e \"require('node:fs').chmodSync('dist/bin.js', 0o755)\"",
48
+ "dev": "tsc --project tsconfig.json --watch",
49
+ "typecheck": "tsc --project tsconfig.json --noEmit",
50
+ "lint": "oxlint",
51
+ "lint:fix": "oxfmt && oxlint --fix",
52
+ "format": "oxfmt",
53
+ "format:check": "oxfmt --check",
54
+ "test": "vitest run"
55
+ },
56
+ "dependencies": {
57
+ "@auden.to/eval-core": "0.1.0-alpha.2",
58
+ "@auden.to/projections": "0.1.0-alpha.2",
59
+ "@auden.to/protocol": "0.1.0-alpha.2",
60
+ "@modelcontextprotocol/sdk": "^1.29.0",
61
+ "citty": "^0.1.6",
62
+ "diff": "^9.0.0"
63
+ },
64
+ "overrides": {
65
+ "fast-uri": "3.1.4"
66
+ },
67
+ "devDependencies": {
68
+ "@types/diff": "^8.0.0",
69
+ "@types/node": "^20.0.0",
70
+ "typescript": "*"
71
+ }
72
+ }