atris 3.47.0 → 3.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+ // det/changelog.js — build a grouped changelog from Conventional-Commits history.
3
+ // Replaces the "summarize what changed since the last release" ask: the sections,
4
+ // order, and bullets come straight from the commit subjects, so the changelog is
5
+ // exact and reproducible, not an LLM paraphrase that drops or invents entries.
6
+ //
7
+ // Usage:
8
+ // node changelog.js # since the last tag (or root) -> markdown
9
+ // node changelog.js v3.34.0 # since a specific ref
10
+ // node changelog.js v3.34.0 HEAD # explicit range
11
+ // node changelog.js --json # structured {sections,counts,...}
12
+ //
13
+ // Reads `git log` itself; no stdin needed. The pure core build(commits) is
14
+ // exported and unit-tested.
15
+
16
+ 'use strict';
17
+
18
+ const { execFileSync } = require('child_process');
19
+
20
+ // --- pure core (no git, no process) ---------------------------------------
21
+
22
+ // Conventional-Commits types -> human section heading, in display order.
23
+ const SECTIONS = [
24
+ ['feat', 'Features'],
25
+ ['fix', 'Fixes'],
26
+ ['perf', 'Performance'],
27
+ ['refactor', 'Refactors'],
28
+ ['docs', 'Docs'],
29
+ ['test', 'Tests'],
30
+ ['build', 'Build'],
31
+ ['ci', 'CI'],
32
+ ['chore', 'Chores'],
33
+ ['other', 'Other'],
34
+ ];
35
+ const KNOWN = new Set(SECTIONS.map((s) => s[0]));
36
+
37
+ // "feat(scope): subject" or "fix: subject" -> { type, scope, subject }.
38
+ // Anything that doesn't match the header grammar lands in the "other" bucket
39
+ // with the whole line as the subject, so nothing is silently dropped.
40
+ function parseSubject(line) {
41
+ const m = /^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/.exec(line.trim());
42
+ if (!m) return { type: 'other', scope: '', breaking: false, subject: line.trim() };
43
+ const type = KNOWN.has(m[1]) ? m[1] : 'other';
44
+ return { type, scope: m[2] || '', breaking: Boolean(m[3]), subject: m[4].trim() };
45
+ }
46
+
47
+ // commits: [{ hash, subject }] -> { sections, counts, breaking, total }
48
+ function build(commits) {
49
+ if (!Array.isArray(commits)) return { error: 'commits must be an array' };
50
+ const buckets = {};
51
+ const breaking = [];
52
+ for (const c of commits) {
53
+ const p = parseSubject(c.subject || '');
54
+ const entry = { hash: c.hash || '', scope: p.scope, subject: p.subject };
55
+ (buckets[p.type] = buckets[p.type] || []).push(entry);
56
+ if (p.breaking) breaking.push(entry);
57
+ }
58
+ const sections = [];
59
+ const counts = {};
60
+ for (const [type, title] of SECTIONS) {
61
+ const items = buckets[type];
62
+ if (items && items.length) {
63
+ sections.push({ type, title, items });
64
+ counts[type] = items.length;
65
+ }
66
+ }
67
+ return { sections, counts, breaking, total: commits.length };
68
+ }
69
+
70
+ // one bullet: "- subject (scope) [hash]" with the optional bits omitted cleanly.
71
+ function fmtItem(it) {
72
+ const scope = it.scope ? ` (${it.scope})` : '';
73
+ const hash = it.hash ? ` [${it.hash}]` : '';
74
+ return `- ${it.subject}${scope}${hash}`;
75
+ }
76
+
77
+ function render(res) {
78
+ const lines = [];
79
+ if (res.breaking.length) {
80
+ lines.push('### ⚠ BREAKING CHANGES');
81
+ for (const it of res.breaking) lines.push(fmtItem(it));
82
+ lines.push('');
83
+ }
84
+ for (const s of res.sections) {
85
+ lines.push(`### ${s.title}`);
86
+ for (const it of s.items) lines.push(fmtItem(it));
87
+ lines.push('');
88
+ }
89
+ if (!lines.length) return 'No changes.';
90
+ return lines.join('\n').trimEnd();
91
+ }
92
+
93
+ // --- git plumbing (impure, only in main) ----------------------------------
94
+
95
+ function lastTag() {
96
+ try {
97
+ return execFileSync('git', ['describe', '--tags', '--abbrev=0'], {
98
+ encoding: 'utf8',
99
+ }).trim();
100
+ } catch (e) {
101
+ return ''; // no tags yet -> changelog from the root commit
102
+ }
103
+ }
104
+
105
+ // range like "v3.34.0..HEAD" (or just "HEAD" when there's no start ref).
106
+ function readCommits(range) {
107
+ const out = execFileSync('git', ['log', '--no-merges', '--pretty=%h%x09%s', range], {
108
+ encoding: 'utf8',
109
+ });
110
+ const commits = [];
111
+ for (const line of out.split('\n')) {
112
+ if (!line.trim()) continue;
113
+ const tab = line.indexOf('\t');
114
+ commits.push({ hash: line.slice(0, tab), subject: line.slice(tab + 1) });
115
+ }
116
+ return commits;
117
+ }
118
+
119
+ function main() {
120
+ const args = process.argv.slice(2).filter((a) => a !== '--json');
121
+ const wantJson = process.argv.includes('--json');
122
+ const start = args[0] || lastTag();
123
+ const end = args[1] || 'HEAD';
124
+ const range = start ? `${start}..${end}` : end;
125
+ let commits;
126
+ try {
127
+ commits = readCommits(range);
128
+ } catch (e) {
129
+ process.stderr.write(`git failed: ${e.message}\n`);
130
+ process.exit(2);
131
+ }
132
+ const res = build(commits);
133
+ if (res.error) {
134
+ process.stderr.write(res.error + '\n');
135
+ process.exit(2);
136
+ }
137
+ if (wantJson) {
138
+ process.stdout.write(JSON.stringify({ range, ...res }, null, 2) + '\n');
139
+ } else {
140
+ process.stdout.write(render(res) + '\n');
141
+ }
142
+ }
143
+
144
+ if (require.main === module) {
145
+ main();
146
+ }
147
+
148
+ module.exports = { build, parseSubject, render, SECTIONS };
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { spawn, spawnSync } = require('node:child_process');
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+ const crypto = require('node:crypto');
8
+
9
+ const DEFAULT_STARTUP_DEADLINE_SECONDS = 90;
10
+ const DEFAULT_MAX_RUNTIME_SECONDS = 3600;
11
+ const USAGE = 'usage: node scripts/det/codex-watchdog.js ' +
12
+ '[--startup-deadline <sec, default 90>] [--max-runtime <sec, default 3600>] ' +
13
+ '[--receipt <path>] -- <command...>';
14
+
15
+ function positiveSeconds(value, flag) {
16
+ const seconds = Number(value);
17
+ if (!Number.isFinite(seconds) || seconds <= 0) {
18
+ throw new Error(`${flag} must be a positive number`);
19
+ }
20
+ return seconds;
21
+ }
22
+
23
+ function parseArgs(argv) {
24
+ let startupDeadlineSeconds = DEFAULT_STARTUP_DEADLINE_SECONDS;
25
+ let maxRuntimeSeconds = DEFAULT_MAX_RUNTIME_SECONDS;
26
+ let receiptPath = '';
27
+ let index = 0;
28
+
29
+ while (index < argv.length && argv[index] !== '--') {
30
+ const flag = argv[index];
31
+ if (flag !== '--startup-deadline' && flag !== '--max-runtime' && flag !== '--receipt') {
32
+ throw new Error(`unknown option: ${flag}`);
33
+ }
34
+ if (index + 1 >= argv.length || argv[index + 1] === '--') {
35
+ throw new Error(`${flag} needs a value`);
36
+ }
37
+ if (flag === '--startup-deadline') {
38
+ startupDeadlineSeconds = positiveSeconds(argv[index + 1], flag);
39
+ } else if (flag === '--max-runtime') {
40
+ maxRuntimeSeconds = positiveSeconds(argv[index + 1], flag);
41
+ } else {
42
+ receiptPath = argv[index + 1];
43
+ }
44
+ index += 2;
45
+ }
46
+
47
+ if (argv[index] !== '--' || index + 1 >= argv.length) {
48
+ throw new Error('missing command after --');
49
+ }
50
+
51
+ return {
52
+ startupDeadlineSeconds,
53
+ maxRuntimeSeconds,
54
+ receiptPath,
55
+ command: argv[index + 1],
56
+ commandArgs: argv.slice(index + 2),
57
+ };
58
+ }
59
+
60
+ function writeTimeoutReceipt(config, exitCode, startedAt) {
61
+ if (!config.receiptPath || (exitCode !== 124 && exitCode !== 125)) return;
62
+ const receiptPath = path.resolve(config.receiptPath);
63
+ const dir = path.dirname(receiptPath);
64
+ fs.mkdirSync(dir, { recursive: true });
65
+ const groupResult = spawnSync('ps', ['-o', 'pgid=', '-p', String(process.pid)], { encoding: 'utf8' });
66
+ const parsedGroup = groupResult.status === 0 ? Number(String(groupResult.stdout || '').trim()) : null;
67
+ const receipt = {
68
+ schema: 'atris.codex_watchdog_receipt.v1',
69
+ status: 'timed_out',
70
+ reason: exitCode === 124 ? 'silent_start' : 'max_runtime',
71
+ exit_code: exitCode,
72
+ pid: process.pid,
73
+ pgid: Number.isInteger(parsedGroup) && parsedGroup > 0 ? parsedGroup : null,
74
+ started_at: startedAt,
75
+ finished_at: new Date().toISOString(),
76
+ };
77
+ const tmpPath = path.join(dir, `.${path.basename(receiptPath)}.${process.pid}.${crypto.randomBytes(4).toString('hex')}.tmp`);
78
+ try {
79
+ fs.writeFileSync(tmpPath, `${JSON.stringify(receipt, null, 2)}\n`);
80
+ fs.renameSync(tmpPath, receiptPath);
81
+ } finally {
82
+ try { fs.unlinkSync(tmpPath); } catch {}
83
+ }
84
+ }
85
+
86
+ function killProcessGroup(child) {
87
+ if (!child.pid) return;
88
+ try {
89
+ process.kill(-child.pid, 'SIGKILL');
90
+ } catch (error) {
91
+ if (error.code === 'ESRCH') return;
92
+ try {
93
+ child.kill('SIGKILL');
94
+ } catch {}
95
+ }
96
+ }
97
+
98
+ function runAttempt(config, remainingRuntimeMs) {
99
+ return new Promise((resolve) => {
100
+ let nullFd;
101
+ let child;
102
+ try {
103
+ nullFd = fs.openSync('/dev/null', 'r');
104
+ child = spawn(config.command, config.commandArgs, {
105
+ detached: true,
106
+ stdio: [nullFd, 'pipe', 'pipe'],
107
+ });
108
+ } catch (error) {
109
+ if (nullFd !== undefined) fs.closeSync(nullFd);
110
+ resolve({ type: 'spawn-error', error });
111
+ return;
112
+ }
113
+ fs.closeSync(nullFd);
114
+
115
+ let sawOutput = false;
116
+ let stopReason = null;
117
+ let spawnError = null;
118
+
119
+ const markStarted = () => {
120
+ sawOutput = true;
121
+ };
122
+ child.stdout.once('data', markStarted);
123
+ child.stderr.once('data', markStarted);
124
+ child.stdout.pipe(process.stdout, { end: false });
125
+ child.stderr.pipe(process.stderr, { end: false });
126
+
127
+ const stop = (reason) => {
128
+ if (stopReason) return;
129
+ stopReason = reason;
130
+ killProcessGroup(child);
131
+ };
132
+
133
+ const startupTimer = setTimeout(() => {
134
+ if (!sawOutput) stop('silent-start');
135
+ }, Math.ceil(config.startupDeadlineSeconds * 1000));
136
+ const runtimeTimer = setTimeout(() => {
137
+ stop('max-runtime');
138
+ }, remainingRuntimeMs);
139
+
140
+ child.once('error', (error) => {
141
+ spawnError = error;
142
+ if (!stopReason) stopReason = 'spawn-error';
143
+ });
144
+ child.once('close', (code, signal) => {
145
+ clearTimeout(startupTimer);
146
+ clearTimeout(runtimeTimer);
147
+ if (spawnError) {
148
+ resolve({ type: 'spawn-error', error: spawnError });
149
+ } else if (stopReason) {
150
+ resolve({ type: stopReason });
151
+ } else {
152
+ resolve({ type: 'exit', code, signal });
153
+ }
154
+ });
155
+ });
156
+ }
157
+
158
+ async function run(config) {
159
+ const startedAt = Date.now();
160
+ const maxRuntimeMs = Math.ceil(config.maxRuntimeSeconds * 1000);
161
+
162
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
163
+ const remainingRuntimeMs = maxRuntimeMs - (Date.now() - startedAt);
164
+ if (remainingRuntimeMs <= 0) {
165
+ process.stderr.write(`watchdog: max runtime of ${config.maxRuntimeSeconds}s exceeded\n`);
166
+ return 125;
167
+ }
168
+
169
+ const result = await runAttempt(config, remainingRuntimeMs);
170
+ if (result.type === 'silent-start') {
171
+ if (attempt === 1) {
172
+ process.stderr.write(
173
+ `watchdog: silent start after ${config.startupDeadlineSeconds}s, retrying once\n`
174
+ );
175
+ continue;
176
+ }
177
+ process.stderr.write('watchdog: silent start twice, giving up\n');
178
+ return 124;
179
+ }
180
+ if (result.type === 'max-runtime') {
181
+ process.stderr.write(`watchdog: max runtime of ${config.maxRuntimeSeconds}s exceeded\n`);
182
+ return 125;
183
+ }
184
+ if (result.type === 'spawn-error') {
185
+ process.stderr.write(`watchdog: could not start command: ${result.error.message}\n`);
186
+ return 127;
187
+ }
188
+ if (result.code !== null) return result.code;
189
+ if (result.signal) {
190
+ process.kill(process.pid, result.signal);
191
+ return 1;
192
+ }
193
+ return 1;
194
+ }
195
+
196
+ return 124;
197
+ }
198
+
199
+ async function main() {
200
+ const startedAt = new Date().toISOString();
201
+ let config;
202
+ try {
203
+ config = parseArgs(process.argv.slice(2));
204
+ } catch (error) {
205
+ process.stderr.write(`watchdog: ${error.message}\n${USAGE}\n`);
206
+ process.exitCode = 2;
207
+ return;
208
+ }
209
+ process.exitCode = await run(config);
210
+ try {
211
+ writeTimeoutReceipt(config, process.exitCode, startedAt);
212
+ } catch (error) {
213
+ process.stderr.write(`watchdog: could not write timeout receipt: ${error.message}\n`);
214
+ }
215
+ }
216
+
217
+ main();
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env node
2
+ // det/commit-msg.js — draft a Conventional-Commits message from the STAGED diff.
3
+ // Replaces the "write me a commit message" ask: the type/scope come from the
4
+ // file paths and the body from the diff stats, so it is exact and reproducible,
5
+ // not an LLM guess about intent.
6
+ //
7
+ // Usage:
8
+ // git add -A && node commit-msg.js # print the drafted message
9
+ // node commit-msg.js --json # structured {type,scope,subject,body,...}
10
+ //
11
+ // Reads `git diff --cached` itself; no stdin needed. Exit 2 if nothing staged.
12
+ // The pure core draft(files) is exported and unit-tested.
13
+
14
+ 'use strict';
15
+
16
+ const { execFileSync } = require('child_process');
17
+
18
+ // --- pure core (no git, no process) ---------------------------------------
19
+
20
+ const VERB = { A: 'add', M: 'update', D: 'remove', R: 'rename', C: 'copy' };
21
+
22
+ function isMd(p) {
23
+ return /\.md$/i.test(p);
24
+ }
25
+ function isTest(p) {
26
+ return /(^|\/)tests?\//.test(p) || /\.test\.[jt]s$/.test(p);
27
+ }
28
+ function isChore(p) {
29
+ return (
30
+ /^(scripts|\.github)\//.test(p) ||
31
+ /(^|\/)(package(-lock)?\.json|\.eslintrc.*|\.gitignore|\.npmignore)$/.test(p) ||
32
+ /\.ya?ml$/.test(p)
33
+ );
34
+ }
35
+
36
+ // scope = basename of the deepest directory common to every changed file.
37
+ function commonDirScope(paths) {
38
+ if (paths.length === 0) return '';
39
+ const dirSegs = paths.map((p) => p.split('/').slice(0, -1));
40
+ let common = dirSegs[0];
41
+ for (const segs of dirSegs.slice(1)) {
42
+ let i = 0;
43
+ while (i < common.length && i < segs.length && common[i] === segs[i]) i += 1;
44
+ common = common.slice(0, i);
45
+ }
46
+ return common.length ? common[common.length - 1] : '';
47
+ }
48
+
49
+ function pickType(files) {
50
+ const paths = files.map((f) => f.path);
51
+ if (paths.every(isMd)) return 'docs';
52
+ if (paths.every(isTest)) return 'test';
53
+ if (paths.every(isChore)) return 'chore';
54
+ if (files.some((f) => f.status === 'A')) return 'feat';
55
+ return 'fix';
56
+ }
57
+
58
+ // The one file that best represents the change: prefer an added file, then the
59
+ // biggest churn, tie-broken by path so the pick is stable across runs.
60
+ function leadFile(files) {
61
+ return [...files].sort((a, b) => {
62
+ const addedA = a.status === 'A' ? 1 : 0;
63
+ const addedB = b.status === 'A' ? 1 : 0;
64
+ if (addedA !== addedB) return addedB - addedA;
65
+ const churnA = (a.added || 0) + (a.deleted || 0);
66
+ const churnB = (b.added || 0) + (b.deleted || 0);
67
+ if (churnA !== churnB) return churnB - churnA;
68
+ return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
69
+ })[0];
70
+ }
71
+
72
+ function summarize(files) {
73
+ const lead = leadFile(files);
74
+ const verb = VERB[lead.status] || 'update';
75
+ const name = lead.path.split('/').pop();
76
+ if (files.length === 1) return `${verb} ${name}`;
77
+ // name the lead file instead of an anonymous count ("update 3 files"):
78
+ // that count is the exact slop this script exists to kill.
79
+ return `${verb} ${name} (+${files.length - 1} more)`;
80
+ }
81
+
82
+ // files: [{ path, status, added, deleted }] -> { type, scope, summary, subject, body, totals }
83
+ function draft(files) {
84
+ if (!Array.isArray(files) || files.length === 0) {
85
+ return { error: 'no staged changes' };
86
+ }
87
+ const type = pickType(files);
88
+ let scope = commonDirScope(files.map((f) => f.path));
89
+ if (scope === type) scope = ''; // avoid redundant test(test): / docs(docs):
90
+ const summary = summarize(files);
91
+ const subject = `${type}${scope ? `(${scope})` : ''}: ${summary}`;
92
+ const totals = files.reduce(
93
+ (a, f) => ({ added: a.added + (f.added || 0), deleted: a.deleted + (f.deleted || 0) }),
94
+ { added: 0, deleted: 0 }
95
+ );
96
+ const lines = files.map(
97
+ (f) => `- ${f.status} ${f.path} (+${f.added || 0}/-${f.deleted || 0})`
98
+ );
99
+ const body = `${lines.join('\n')}\n\n${files.length} file${
100
+ files.length === 1 ? '' : 's'
101
+ } changed, +${totals.added}/-${totals.deleted}`;
102
+ return { type, scope, summary, subject, body, totals, files };
103
+ }
104
+
105
+ // --- git plumbing (impure, only in main) ----------------------------------
106
+
107
+ // Merge `--numstat` (added/deleted) with `--name-status` (A/M/D) by path.
108
+ function readStaged() {
109
+ const numstat = execFileSync('git', ['diff', '--cached', '--numstat'], { encoding: 'utf8' });
110
+ const names = execFileSync('git', ['diff', '--cached', '--name-status'], { encoding: 'utf8' });
111
+ const stat = {};
112
+ for (const line of numstat.split('\n')) {
113
+ if (!line.trim()) continue;
114
+ const [added, deleted, path] = line.split('\t');
115
+ stat[path] = { added: added === '-' ? 0 : Number(added), deleted: deleted === '-' ? 0 : Number(deleted) };
116
+ }
117
+ const files = [];
118
+ for (const line of names.split('\n')) {
119
+ if (!line.trim()) continue;
120
+ const parts = line.split('\t');
121
+ const status = parts[0][0]; // R100 -> R
122
+ const path = parts[parts.length - 1];
123
+ files.push({ path, status, added: (stat[path] || {}).added || 0, deleted: (stat[path] || {}).deleted || 0 });
124
+ }
125
+ return files;
126
+ }
127
+
128
+ function main() {
129
+ const wantJson = process.argv.includes('--json');
130
+ let files;
131
+ try {
132
+ files = readStaged();
133
+ } catch (e) {
134
+ process.stderr.write(`git failed: ${e.message}\n`);
135
+ process.exit(2);
136
+ }
137
+ const res = draft(files);
138
+ if (res.error) {
139
+ process.stderr.write(res.error + '\n');
140
+ process.exit(2);
141
+ }
142
+ if (wantJson) {
143
+ process.stdout.write(JSON.stringify(res, null, 2) + '\n');
144
+ } else {
145
+ process.stdout.write(`${res.subject}\n\n${res.body}\n`);
146
+ }
147
+ }
148
+
149
+ if (require.main === module) {
150
+ main();
151
+ }
152
+
153
+ module.exports = { draft, commonDirScope, pickType, summarize, leadFile };
@@ -0,0 +1,81 @@
1
+ {"message": "what is the capital of france", "lane": "fast", "why": "short factual lookup"}
2
+ {"message": "list the files in the atris runs folder", "lane": "fast", "why": "simple enumeration"}
3
+ {"message": "who wrote the little prince", "lane": "fast", "why": "single fact"}
4
+ {"message": "define idempotent", "lane": "fast", "why": "definition lookup"}
5
+ {"message": "when was node 22 released", "lane": "fast", "why": "date lookup"}
6
+ {"message": "show me the npm version command", "lane": "fast", "why": "one-liner recall"}
7
+ {"message": "what does http 429 mean", "lane": "fast", "why": "status code lookup"}
8
+ {"message": "where does atris store credentials", "lane": "fast", "why": "single known fact"}
9
+ {"message": "list 5 postgres index types", "lane": "fast", "why": "bounded list recall"}
10
+ {"message": "what port does redis use by default", "lane": "fast", "why": "single fact"}
11
+ {"message": "convert 90 fahrenheit to celsius", "lane": "fast", "why": "single computation"}
12
+ {"message": "what is a monad", "lane": "fast", "why": "definition lookup"}
13
+ {"message": "summarize this in one line: the meeting moved to thursday and derrick will demo the orb", "lane": "fast", "why": "trivial transform"}
14
+ {"message": "write a friendly two line slack message telling the team the deploy is done", "lane": "pro", "why": "light generation with tone"}
15
+ {"message": "explain how our wish loop works to a new hire", "lane": "pro", "why": "explanation needs context and structure"}
16
+ {"message": "draft a short email to a customer asking to reschedule tomorrows call", "lane": "pro", "why": "everyday writing"}
17
+ {"message": "give me three name ideas for a cli that routes work between ai models", "lane": "pro", "why": "light creative generation"}
18
+ {"message": "rewrite this paragraph so it sounds less formal: our organization has determined that the aforementioned initiative shall proceed", "lane": "pro", "why": "mid-weight rewrite"}
19
+ {"message": "whats a good way to onboard a non technical founder to git", "lane": "pro", "why": "advice, some judgment"}
20
+ {"message": "turn these bullet points into a short update for investors: shipped router, closed two deals, hired one engineer", "lane": "pro", "why": "structured writing"}
21
+ {"message": "help me think through whether to charge per seat or per usage", "lane": "pro", "why": "reasoning but conversational scope"}
22
+ {"message": "explain the difference between optimistic and pessimistic locking with an example", "lane": "pro", "why": "explanation with example"}
23
+ {"message": "make this tweet punchier: we launched a thing that picks the right ai model for you", "lane": "pro", "why": "short edit with taste"}
24
+ {"message": "what should i ask in a reference call for a senior engineer", "lane": "pro", "why": "judgment list"}
25
+ {"message": "design a database schema for a multi tenant task system with per org roles, audit history, and soft deletes, and explain the tradeoffs of your choices", "lane": "max", "why": "design plus tradeoff analysis"}
26
+ {"message": "architect a migration plan to move our monolith to services without downtime, including rollout order and rollback points", "lane": "max", "why": "long horizon architecture"}
27
+ {"message": "prove that this retry strategy cannot livelock, or show a counterexample", "lane": "max", "why": "proof style reasoning"}
28
+ {"message": "analyze the tradeoffs between event sourcing and crud for our billing system and recommend one with reasoning", "lane": "max", "why": "deep comparison and recommendation"}
29
+ {"message": "plan a three month roadmap to take the router from heuristic to learned routing, with milestones, risks, and what we measure at each step", "lane": "max", "why": "multi step planning"}
30
+ {"message": "compare the tradeoffs of thompson sampling versus epsilon greedy for picking models when feedback is delayed and noisy, and which fits our receipt data", "lane": "max", "why": "deep technical comparison"}
31
+ {"message": "why might a distributed lock built on redis fail under network partition, and how would you design around each failure mode", "lane": "max", "why": "failure mode analysis"}
32
+ {"message": "design an experiment to test whether our auto router saves money without hurting answer quality, including sample size reasoning", "lane": "max", "why": "experiment design"}
33
+ {"message": "walk through what happens when two mission ticks race on the same task file and design a fix that keeps receipts consistent", "lane": "max", "why": "concurrency analysis and design"}
34
+ {"message": "should atris build its own inference layer or stay on provider apis for the next two years, argue both sides then commit", "lane": "max", "why": "strategic analysis"}
35
+ {"message": "fix this: TypeError: Cannot read properties of undefined (reading 'map')\n at buildRoster (lib/fleet.js:412)\n at dispatch (lib/fleet.js:2101)", "lane": "code-fast", "why": "stack trace plus fix verb"}
36
+ {"message": "refactor this function to use early returns:\n```js\nfunction pick(a){ if(a){ if(a.ok){ return a.v } else { return null } } else { return null } }\n```", "lane": "code-fast", "why": "code fence plus refactor verb"}
37
+ {"message": "debug why this test fails:\n```js\nassert.equal(pickLane('what is x').lane, 'fast')\n```\nit returns pro", "lane": "code-fast", "why": "code fence plus debug verb"}
38
+ {"message": "rename the variable cnt to receiptCount in this snippet:\n```js\nlet cnt = rows.length\nreturn cnt\n```", "lane": "code-fast", "why": "bounded mechanical edit"}
39
+ {"message": "fix the off by one in this loop:\n```python\nfor i in range(len(xs) - 1):\n print(xs[i])\n```", "lane": "code-fast", "why": "small bounded code fix"}
40
+ {"message": "why is this promise never resolving:\n```js\nnew Promise((resolve) => { if (ready) resolve() })\n```", "lane": "code-fast", "why": "bounded code diagnosis"}
41
+ {"message": "what is the difference between let and const", "lane": "fast", "why": "boundary: code topic but pure lookup, no edit"}
42
+ {"message": "prove p equals np", "lane": "max", "why": "boundary: very short but proof depth"}
43
+ {"message": "is rust better than go", "lane": "pro", "why": "boundary: short but needs judgment not a fact"}
44
+ {"message": "summarize the plot of hamlet", "lane": "fast", "why": "boundary: summary of known fact, no reasoning"}
45
+ {"message": "write a haiku about deploy friday", "lane": "pro", "why": "boundary: short creative, taste over recall"}
46
+ {"message": "list the tradeoffs of microservices", "lane": "pro", "why": "boundary: list verb but needs judgment beyond recall"}
47
+ {"message": "should we rewrite the backend in rust, consider team skills, hiring, our latency needs, migration cost, and what we lose by pausing features for two quarters", "lane": "max", "why": "boundary: starts casual but multi factor decision"}
48
+ {"message": "fix my code", "lane": "pro", "why": "boundary: fix verb but no code included, needs clarification not a code lane"}
49
+ {"message": "what are the seven capabilities in our router checklist and which two are unfinished, and for the unfinished ones sketch the implementation approach and the riskiest assumption in each", "lane": "max", "why": "boundary: starts as lookup, second half is analysis"}
50
+ {"message": "hey", "lane": "fast", "why": "boundary: greeting, cheapest lane"}
51
+ {"message": "thanks that worked", "lane": "fast", "why": "boundary: acknowledgment, cheapest lane"}
52
+ {"message": "explain this error in plain words: ENOTEMPTY directory not empty rm", "lane": "fast", "why": "boundary: error text but explanation lookup, no code to edit"}
53
+ {"message": "does postgres support partial indexes", "lane": "fast", "why": "yes/no capability lookup, found in dogfood 7/21"}
54
+ {"message": "my build fails with ELIFECYCLE after npm install, what do i check first", "lane": "pro", "why": "troubleshooting advice not recall, found in dogfood 7/21"}
55
+ {"message": "rank our 5 engines by cost per successful task and tell me which to cancel, consider subscription price, pass rate, and speed", "lane": "max", "why": "multi factor ranking decision, found in dogfood 7/21"}
56
+ {"message": "whos on call this week", "lane": "fast", "why": "contracted lookup word, found in dogfood tick 2"}
57
+ {"message": "whats the git command to undo the last commit but keep changes", "lane": "fast", "why": "command recall, found in dogfood tick 2"}
58
+ {"message": "my mac fan is screaming when i run the test suite, is that normal", "lane": "pro", "why": "lookup word mid sentence is not a lookup, found in dogfood tick 2"}
59
+ {"message": "estimate how much we save per month if fast handles 40% of turns, pro 50%, max 10%, versus everything on max, show your math", "lane": "max", "why": "multi step estimation, found in dogfood tick 2"}
60
+ {"message": "if we double the price and lose a third of customers is that good, walk through the revenue and support load math", "lane": "max", "why": "walk through the math is analysis, found in dogfood tick 2"}
61
+ {"message": "how do i exit vim lol", "lane": "fast", "why": "muscle memory lookup, found in dogfood tick 3"}
62
+ {"message": "so we have 3 pricing ideas, flat 20 a month, usage based, or free with paid packs, think about who each attracts, what support looks like, and which one kills us if we guess wrong", "lane": "max", "why": "multi option strategy weighing, found in dogfood tick 3"}
63
+ {"message": "WHATS THE WIFI PASSWORD FORMAT WE USE FOR GUESTS", "lane": "fast", "why": "caps lookup held in dogfood tick 3"}
64
+ {"message": "im getting 401s from the backend since an hour ago but only on the mac app, web works fine, where do i even start", "lane": "pro", "why": "troubleshooting with mid sentence where, held in dogfood tick 3"}
65
+ {"message": "turn this slack thread into one decision line: derrick: can we ship tmrw? me: tests green. derrick: ok but whats the risk? me: rollback is one command. derrick: send it", "lane": "pro", "why": "pasted thread with internal question marks is a transform, found in dogfood tick 4"}
66
+ {"message": "que significa el error 502 bad gateway", "lane": "fast", "why": "spanish lookup, found in dogfood tick 4"}
67
+ {"message": "why is my regex not matching: /^[a-z]+$/ against the string Hello", "lane": "code-fast", "why": "regex diagnosis without a fence, found in dogfood tick 4"}
68
+ {"message": "summarize what changed in our router this week for the changelog", "lane": "pro", "why": "possessive context work not a paste transform, found in dogfood tick 4"}
69
+ {"message": "is consciousness computable", "lane": "pro", "why": "short but bottomless, yes/no shape is a trap, found in dogfood tick 5"}
70
+ {"message": "settle it once and for all, tabs or spaces", "lane": "pro", "why": "banter judgment, held in dogfood tick 5"}
71
+ {"message": "and the second one?", "lane": "fast", "why": "context fragment, cheapest lane until session stickiness exists, held in dogfood tick 5"}
72
+ {"message": "whats blocking the demo", "lane": "fast", "why": "bounded workspace status lookup, held in dogfood tick 5"}
73
+ {"message": "whens the next stripe payout", "lane": "fast", "why": "contracted when lookup, found in dogfood tick 6"}
74
+ {"message": "este codigo tiene un bug:\n```js\nconst total = items.reduce((a,b) => a + b.price)\n```", "lane": "code-fast", "why": "spanish bug report with fence, found in dogfood tick 6"}
75
+ {"message": "if the router picks wrong lanes 20% of the time but each wrong pick costs 2 cents extra, do we even care, math it out", "lane": "max", "why": "expected value analysis, found in dogfood tick 6"}
76
+ {"message": "is bun faster than node", "lane": "fast", "why": "measurable comparative, held as fast in dogfood tick 6"}
77
+ {"message": "translate our tagline to german and french", "lane": "pro", "why": "possessive needs workspace context, held in dogfood tick 6"}
78
+ {"message": "PROD IS DOWN users cant login everything 500s since 5 min ago", "lane": "max", "why": "live incident, stakes beat size, found in dogfood tick 7"}
79
+ {"message": "do we log ip addresses anywhere, legal is asking", "lane": "pro", "why": "compliance question must not route cheap, found in dogfood tick 7"}
80
+ {"message": "draft terms of service for the router beta, cover liability for wrong lane picks, data retention for the picks log, and how we handle eu users", "lane": "max", "why": "legal drafting with multiple requirements, found in dogfood tick 7"}
81
+ {"message": "urgent: investor asked for our churn number before their 9am, where do i pull it and whats the caveat i should mention", "lane": "pro", "why": "urgent workspace pull with judgment, held in dogfood tick 7"}
@@ -0,0 +1,20 @@
1
+ {"message": "whats the flag to skip git hooks", "lane": "fast", "why": "single flag lookup"}
2
+ {"message": "how many megabytes in a gigabyte", "lane": "fast", "why": "single fact"}
3
+ {"message": "show the last 5 commits", "lane": "fast", "why": "one command recall"}
4
+ {"message": "define eventual consistency", "lane": "fast", "why": "definition"}
5
+ {"message": "translate good morning to spanish", "lane": "fast", "why": "tiny transform"}
6
+ {"message": "gm", "lane": "fast", "why": "greeting"}
7
+ {"message": "sounds good", "lane": "fast", "why": "acknowledgment"}
8
+ {"message": "write a birthday message for my cofounder who loves espresso", "lane": "pro", "why": "light personal writing"}
9
+ {"message": "make this subject line better: quarterly update for investors q3", "lane": "pro", "why": "short edit with taste"}
10
+ {"message": "how do i tell a customer their feature request is not happening without losing them", "lane": "pro", "why": "delicate wording, judgment"}
11
+ {"message": "give me a checklist for taking the laptop abroad for a month of remote work", "lane": "pro", "why": "practical list with judgment"}
12
+ {"message": "is it worth adding typescript to a 5k line node project", "lane": "pro", "why": "short judgment question"}
13
+ {"message": "explain webhooks to a marketer", "lane": "pro", "why": "audience-shaped explanation"}
14
+ {"message": "design a rate limiter for our public api that is fair across tenants, survives restarts, and degrades gracefully under redis loss, justify each choice", "lane": "max", "why": "design with justification"}
15
+ {"message": "our churn doubled last quarter while nps stayed flat, lay out the possible causes, how you would test each, and what data we need", "lane": "max", "why": "causal analysis plan"}
16
+ {"message": "prove this scheduler never starves a low priority task, or find the case where it does", "lane": "max", "why": "proof style"}
17
+ {"message": "plan how we migrate 40 million rows to a new schema with zero downtime, include batch sizing, verification, and rollback", "lane": "max", "why": "long horizon plan"}
18
+ {"message": "should we open source the router, weigh community growth, competitive risk, maintenance burden, and monetization paths", "lane": "max", "why": "multi factor decision"}
19
+ {"message": "fix this test:\n```js\nassert.equal(sum([1,2]), 4)\n```\nsum works fine elsewhere", "lane": "code-fast", "why": "code fence plus fix"}
20
+ {"message": "why does this throw:\n```python\nx = {}\nprint(x['missing'])\n```", "lane": "code-fast", "why": "code fence plus diagnosis"}