atris 3.46.1 → 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,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"}
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ // det/date.js — deterministic date/time conversion. Epoch<->ISO and weekday are
3
+ // the asks LLMs fumble most (seconds vs ms, and timezone guesses). Everything is
4
+ // UTC so the answer is the same on every machine. Reads stdin, writes stdout.
5
+ //
6
+ // Usage:
7
+ // echo 1700000000 | node date.js iso # epoch (s or ms) -> ISO 8601 UTC
8
+ // echo 2026-07-07 | node date.js epoch # date/ISO -> epoch seconds
9
+ // echo 2026-07-07 | node date.js epochms # -> epoch milliseconds
10
+ // echo 2026-07-07 | node date.js weekday # -> Monday..Sunday (UTC)
11
+ //
12
+ // Modes: iso | epoch | epochms | weekday
13
+ // Bare date strings (no timezone) are read as UTC. Exit 2 on bad mode/input.
14
+
15
+ 'use strict';
16
+
17
+ const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
18
+
19
+ // Parse stdin into a Date, deterministically. A pure-digit string is an epoch
20
+ // (>=13 digits = ms, else seconds). Otherwise a date string; if it carries no
21
+ // timezone we pin it to UTC by appending 'Z' so machines don't disagree.
22
+ function toDate(s) {
23
+ const t = s.trim();
24
+ if (t === '') return { error: 'empty input' };
25
+ if (/^-?\d+$/.test(t)) {
26
+ const n = Number(t);
27
+ const ms = t.replace('-', '').length >= 13 ? n : n * 1000;
28
+ return { date: new Date(ms) };
29
+ }
30
+ // ISO-ish without an explicit zone/offset -> treat as UTC.
31
+ let str = t;
32
+ const hasZone = /[zZ]$|[+-]\d{2}:?\d{2}$/.test(t);
33
+ if (!hasZone) {
34
+ str = /\d{4}-\d{2}-\d{2}$/.test(t) ? t + 'T00:00:00Z' : t + 'Z';
35
+ }
36
+ const d = new Date(str);
37
+ if (Number.isNaN(d.getTime())) return { error: `cannot parse date: ${t}` };
38
+ return { date: d };
39
+ }
40
+
41
+ // Pure core: returns { text } or { error }.
42
+ function run(mode, input) {
43
+ const p = toDate(input);
44
+ if (p.error) return { error: p.error };
45
+ const d = p.date;
46
+ switch (mode) {
47
+ case 'iso':
48
+ return { text: d.toISOString() };
49
+ case 'epoch':
50
+ return { text: String(Math.floor(d.getTime() / 1000)) };
51
+ case 'epochms':
52
+ return { text: String(d.getTime()) };
53
+ case 'weekday':
54
+ return { text: DAYS[d.getUTCDay()] };
55
+ default:
56
+ return { error: `unknown mode: ${mode}` };
57
+ }
58
+ }
59
+
60
+ function readStdin() {
61
+ return new Promise((resolve) => {
62
+ let data = '';
63
+ process.stdin.setEncoding('utf8');
64
+ process.stdin.on('data', (c) => (data += c));
65
+ process.stdin.on('end', () => resolve(data));
66
+ if (process.stdin.isTTY) resolve('');
67
+ });
68
+ }
69
+
70
+ const MODES = ['iso', 'epoch', 'epochms', 'weekday'];
71
+
72
+ async function main() {
73
+ const mode = process.argv.slice(2).find((a) => !a.startsWith('-'));
74
+ if (!mode || !MODES.includes(mode)) {
75
+ process.stderr.write(`unknown mode: ${mode || '(none)'}\nmodes: ${MODES.join(' | ')}\n`);
76
+ process.exit(2);
77
+ }
78
+ const input = await readStdin();
79
+ const res = run(mode, input);
80
+ if (res.error) {
81
+ process.stderr.write(res.error + '\n');
82
+ process.exit(2);
83
+ }
84
+ if (res.text.length) process.stdout.write(res.text + '\n');
85
+ }
86
+
87
+ if (require.main === module) {
88
+ main();
89
+ }
90
+
91
+ module.exports = { run, toDate, MODES };
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ // det/det.js — one entrypoint for the deterministic task scripts. A cheap model
3
+ // runs `node det.js` to see the whole catalog, then `node det.js <script> <mode>`
4
+ // to route its stdin through the right one. No need to know the file layout.
5
+ //
6
+ // node det.js # print the catalog (task -> script -> modes)
7
+ // node det.js --json # same, machine-readable
8
+ // node det.js extract urls < f # route stdin through extract.js in urls mode
9
+ // node det.js json csv < arr.json # route stdin through json.js in csv mode
10
+ //
11
+ // The catalog is derived from the scripts themselves (their exported MODES /
12
+ // EXTRACTORS), so it can never drift from what actually runs.
13
+
14
+ 'use strict';
15
+
16
+ const extract = require('./extract');
17
+ const json = require('./json');
18
+ const text = require('./text');
19
+ const hash = require('./hash');
20
+ const date = require('./date');
21
+ const voice = require('./voice');
22
+
23
+ // git-facing scripts: they read the repo, not stdin, so they aren't routable
24
+ // through det.js. Listed here only so the front door surfaces all the tools —
25
+ // a cheap model running `det.js` sees these too and knows to run them directly.
26
+ const GIT_SCRIPTS = [
27
+ {
28
+ name: 'commit-msg',
29
+ ask: 'draft a Conventional-Commits message from the staged diff',
30
+ usage: 'git add -A && node scripts/det/commit-msg.js',
31
+ },
32
+ {
33
+ name: 'changelog',
34
+ ask: 'group commits since a ref/tag into a changelog',
35
+ usage: 'node scripts/det/changelog.js [ref]',
36
+ },
37
+ {
38
+ name: 'pr-description',
39
+ ask: 'draft a PR title + area summary + test-plan from the branch diff',
40
+ usage: 'node scripts/det/pr-description.js [base]',
41
+ },
42
+ ];
43
+
44
+ // script -> { ask, modes, run(mode, input) -> {text}|{error} }
45
+ const CATALOG = {
46
+ extract: {
47
+ ask: 'pull links / emails / code / numbers out of text',
48
+ modes: Object.keys(extract.EXTRACTORS),
49
+ run: (mode, input) => {
50
+ const items = extract.extract(mode, input);
51
+ return items === null ? { error: `unknown mode: ${mode}` } : { text: items.join('\n') };
52
+ },
53
+ },
54
+ json: {
55
+ ask: 'reformat / validate / flatten JSON (incl. JSON->CSV)',
56
+ modes: json.MODES,
57
+ run: json.run,
58
+ },
59
+ text: {
60
+ ask: 'dedupe / sort / count / slugify / trim lines',
61
+ modes: text.MODES,
62
+ run: text.run,
63
+ },
64
+ hash: {
65
+ ask: 'base64 / hex encode-decode, sha256 / sha1 / md5',
66
+ modes: hash.MODES,
67
+ run: hash.run,
68
+ },
69
+ date: {
70
+ ask: 'epoch <-> ISO, weekday (all UTC)',
71
+ modes: date.MODES,
72
+ run: date.run,
73
+ },
74
+ voice: {
75
+ ask: 'score a chat reply against the way of talking (PASS or findings)',
76
+ modes: voice.MODES,
77
+ run: voice.run,
78
+ },
79
+ };
80
+
81
+ function catalogText() {
82
+ const rows = Object.entries(CATALOG).map(
83
+ ([name, s]) => ` ${name.padEnd(9)} ${s.modes.join(' ')}\n ${s.ask}`
84
+ );
85
+ const gitRows = GIT_SCRIPTS.map((g) => ` ${g.name.padEnd(15)} ${g.usage}\n ${g.ask}`);
86
+ return (
87
+ 'deterministic task scripts — run: node det.js <script> <mode> < input\n\n' +
88
+ rows.join('\n\n') +
89
+ '\n\ngit-facing (read the repo, run the script directly; not via det.js):\n\n' +
90
+ gitRows.join('\n\n') +
91
+ '\n'
92
+ );
93
+ }
94
+
95
+ function catalogJson() {
96
+ const out = {};
97
+ for (const [name, s] of Object.entries(CATALOG)) out[name] = { ask: s.ask, modes: s.modes };
98
+ const git = {};
99
+ for (const g of GIT_SCRIPTS) git[g.name] = { ask: g.ask, usage: g.usage };
100
+ return JSON.stringify({ ...out, git }, null, 2);
101
+ }
102
+
103
+ function readStdin() {
104
+ return new Promise((resolve) => {
105
+ let data = '';
106
+ process.stdin.setEncoding('utf8');
107
+ process.stdin.on('data', (c) => (data += c));
108
+ process.stdin.on('end', () => resolve(data));
109
+ if (process.stdin.isTTY) resolve('');
110
+ });
111
+ }
112
+
113
+ async function main() {
114
+ const args = process.argv.slice(2).filter((a) => a !== '--json');
115
+ const wantJson = process.argv.includes('--json');
116
+ const [script, mode] = args;
117
+
118
+ if (!script) {
119
+ process.stdout.write((wantJson ? catalogJson() : catalogText()) + '\n');
120
+ return;
121
+ }
122
+ const git = GIT_SCRIPTS.find((g) => g.name === script);
123
+ if (git) {
124
+ process.stdout.write(`${git.name} reads the repo, not stdin — run it directly:\n ${git.usage}\n`);
125
+ return;
126
+ }
127
+ const entry = CATALOG[script];
128
+ if (!entry) {
129
+ process.stderr.write(`unknown script: ${script}\nscripts: ${Object.keys(CATALOG).join(' | ')}\n`);
130
+ process.exit(2);
131
+ }
132
+ if (!mode || !entry.modes.includes(mode)) {
133
+ process.stderr.write(`unknown mode: ${mode || '(none)'}\nmodes: ${entry.modes.join(' | ')}\n`);
134
+ process.exit(2);
135
+ }
136
+ const input = await readStdin();
137
+ const res = entry.run(mode, input);
138
+ if (res.error) {
139
+ process.stderr.write(res.error + '\n');
140
+ process.exit(2);
141
+ }
142
+ if (res.text.length) process.stdout.write(res.text + '\n');
143
+ }
144
+
145
+ if (require.main === module) {
146
+ main();
147
+ }
148
+
149
+ module.exports = { CATALOG, catalogJson, catalogText, GIT_SCRIPTS };
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env node
2
+ // det/extract.js — deterministically pull structured items out of text.
3
+ // Replaces the "extract all the X from this" ask that a cheap LLM does slowly
4
+ // and sometimes wrong. Reads stdin, writes one item per line to stdout.
5
+ //
6
+ // Usage:
7
+ // cat file.txt | node extract.js urls
8
+ // node extract.js emails < file.txt
9
+ // node extract.js code < README.md # fenced ```code blocks
10
+ // node extract.js numbers < report.txt
11
+ // node extract.js --json urls < file.txt # JSON array instead of lines
12
+ //
13
+ // Kinds: urls | emails | code | numbers | ipv4 | hashtags
14
+ // Exit 0 with output, exit 2 on bad/unknown kind. Duplicates removed, order preserved.
15
+
16
+ 'use strict';
17
+
18
+ const EXTRACTORS = {
19
+ urls: (t) => match(t, /\bhttps?:\/\/[^\s<>"')\]]+/g).map(stripTrailingPunct),
20
+ emails: (t) => match(t, /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g),
21
+ ipv4: (t) => match(t, /\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b/g),
22
+ hashtags: (t) => match(t, /(?:^|\s)(#[A-Za-z0-9_]+)/g).map((m) => m.trim()),
23
+ numbers: (t) => match(t, /-?\b\d[\d,]*(?:\.\d+)?\b/g),
24
+ code: (t) => {
25
+ // Fenced blocks: ```lang\n...\n``` — return block contents (not fences).
26
+ const blocks = [];
27
+ const re = /```[^\n]*\n([\s\S]*?)```/g;
28
+ let m;
29
+ while ((m = re.exec(t)) !== null) blocks.push(m[1].replace(/\n$/, ''));
30
+ return blocks;
31
+ },
32
+ };
33
+
34
+ function match(text, re) {
35
+ return text.match(re) || [];
36
+ }
37
+
38
+ function stripTrailingPunct(s) {
39
+ return s.replace(/[.,;:!?]+$/, '');
40
+ }
41
+
42
+ function dedupePreserveOrder(items) {
43
+ const seen = new Set();
44
+ const out = [];
45
+ for (const it of items) {
46
+ if (!seen.has(it)) {
47
+ seen.add(it);
48
+ out.push(it);
49
+ }
50
+ }
51
+ return out;
52
+ }
53
+
54
+ function extract(kind, text) {
55
+ const fn = EXTRACTORS[kind];
56
+ if (!fn) return null;
57
+ return dedupePreserveOrder(fn(text));
58
+ }
59
+
60
+ function readStdin() {
61
+ return new Promise((resolve) => {
62
+ let data = '';
63
+ process.stdin.setEncoding('utf8');
64
+ process.stdin.on('data', (c) => (data += c));
65
+ process.stdin.on('end', () => resolve(data));
66
+ if (process.stdin.isTTY) resolve('');
67
+ });
68
+ }
69
+
70
+ async function main() {
71
+ const args = process.argv.slice(2);
72
+ const json = args.includes('--json');
73
+ const kind = args.find((a) => !a.startsWith('-'));
74
+ if (!kind || !EXTRACTORS[kind]) {
75
+ process.stderr.write(
76
+ `unknown kind: ${kind || '(none)'}\nkinds: ${Object.keys(EXTRACTORS).join(' | ')}\n`
77
+ );
78
+ process.exit(2);
79
+ }
80
+ const text = await readStdin();
81
+ const items = extract(kind, text);
82
+ if (json) {
83
+ process.stdout.write(JSON.stringify(items) + '\n');
84
+ } else if (items.length) {
85
+ process.stdout.write(items.join('\n') + '\n');
86
+ }
87
+ }
88
+
89
+ if (require.main === module) {
90
+ main();
91
+ }
92
+
93
+ module.exports = { extract, EXTRACTORS };
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ // det/hash.js — deterministic encode / hash. The "base64 this" and "give me the
3
+ // sha256" asks an LLM fakes or does wrong. Reads stdin, writes stdout.
4
+ //
5
+ // Usage:
6
+ // printf 'hi' | node hash.js b64 # base64 encode
7
+ // node hash.js b64d < encoded.txt # base64 decode
8
+ // node hash.js sha256 < file.txt # hex sha256 of the bytes
9
+ // node hash.js sha1 < file.txt
10
+ // node hash.js md5 < file.txt
11
+ // node hash.js hexenc < file.txt # raw -> hex
12
+ // node hash.js hexdec < hex.txt # hex -> raw
13
+ //
14
+ // Modes: b64 | b64d | sha256 | sha1 | md5 | hexenc | hexdec
15
+ // Input's trailing newline is stripped before encoding/hashing so
16
+ // `printf 'hi'` and `echo hi` give the same result. Exit 2 on bad mode/input.
17
+
18
+ 'use strict';
19
+
20
+ const crypto = require('crypto');
21
+
22
+ const DIGESTS = { sha256: 'sha256', sha1: 'sha1', md5: 'md5' };
23
+
24
+ // Pure core: returns { text } or { error }. Unit-testable.
25
+ function run(mode, input) {
26
+ // Strip a single trailing newline so shell echo vs printf agree.
27
+ const raw = input.replace(/\n$/, '');
28
+ if (DIGESTS[mode]) {
29
+ return { text: crypto.createHash(DIGESTS[mode]).update(raw, 'utf8').digest('hex') };
30
+ }
31
+ switch (mode) {
32
+ case 'b64':
33
+ return { text: Buffer.from(raw, 'utf8').toString('base64') };
34
+ case 'b64d':
35
+ return { text: Buffer.from(raw, 'base64').toString('utf8') };
36
+ case 'hexenc':
37
+ return { text: Buffer.from(raw, 'utf8').toString('hex') };
38
+ case 'hexdec':
39
+ if (!/^[0-9a-fA-F]*$/.test(raw) || raw.length % 2 !== 0) {
40
+ return { error: 'hexdec needs an even-length hex string' };
41
+ }
42
+ return { text: Buffer.from(raw, 'hex').toString('utf8') };
43
+ default:
44
+ return { error: `unknown mode: ${mode}` };
45
+ }
46
+ }
47
+
48
+ function readStdin() {
49
+ return new Promise((resolve) => {
50
+ let data = '';
51
+ process.stdin.setEncoding('utf8');
52
+ process.stdin.on('data', (c) => (data += c));
53
+ process.stdin.on('end', () => resolve(data));
54
+ if (process.stdin.isTTY) resolve('');
55
+ });
56
+ }
57
+
58
+ const MODES = ['b64', 'b64d', 'sha256', 'sha1', 'md5', 'hexenc', 'hexdec'];
59
+
60
+ async function main() {
61
+ const mode = process.argv.slice(2).find((a) => !a.startsWith('-'));
62
+ if (!mode || !MODES.includes(mode)) {
63
+ process.stderr.write(`unknown mode: ${mode || '(none)'}\nmodes: ${MODES.join(' | ')}\n`);
64
+ process.exit(2);
65
+ }
66
+ const input = await readStdin();
67
+ const res = run(mode, input);
68
+ if (res.error) {
69
+ process.stderr.write(res.error + '\n');
70
+ process.exit(2);
71
+ }
72
+ if (res.text.length) process.stdout.write(res.text + '\n');
73
+ }
74
+
75
+ if (require.main === module) {
76
+ main();
77
+ }
78
+
79
+ module.exports = { run, MODES };
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ // det/hunk-filter.js - keep only unified-diff hunks whose lines match a regex.
3
+ // For concurrent-editor workspaces: stage YOUR hunk of a shared file without
4
+ // sweeping in other agents' churn (git apply --cached the filtered patch).
5
+ //
6
+ // Usage:
7
+ // git diff -U1 -- path/file | node scripts/det/hunk-filter.js "<regex>"
8
+ // git diff -U1 -- path/file | node scripts/det/hunk-filter.js "Horizon" | git apply --cached --unidiff-zero -
9
+ //
10
+ // A file section is printed only when at least one of its hunks matches.
11
+ // Exit 0 on success (even if nothing matched), 2 on missing pattern.
12
+ 'use strict';
13
+
14
+ function filterHunks(diffText, pattern) {
15
+ const re = new RegExp(pattern);
16
+ const lines = String(diffText).split('\n');
17
+ const out = [];
18
+ let header = [];
19
+ let hunk = null;
20
+ let fileHasMatch = false;
21
+ let fileHunks = [];
22
+
23
+ const flushFile = () => {
24
+ if (fileHasMatch && fileHunks.length) {
25
+ out.push(...header, ...fileHunks);
26
+ }
27
+ header = [];
28
+ fileHunks = [];
29
+ fileHasMatch = false;
30
+ };
31
+ const flushHunk = () => {
32
+ if (!hunk) return;
33
+ if (hunk.some((l) => re.test(l))) {
34
+ fileHunks.push(...hunk);
35
+ fileHasMatch = true;
36
+ }
37
+ hunk = null;
38
+ };
39
+
40
+ for (const line of lines) {
41
+ if (line.startsWith('diff --git ')) {
42
+ flushHunk();
43
+ flushFile();
44
+ header = [line];
45
+ } else if (line.startsWith('@@')) {
46
+ flushHunk();
47
+ hunk = [line];
48
+ } else if (hunk) {
49
+ hunk.push(line);
50
+ } else {
51
+ header.push(line);
52
+ }
53
+ }
54
+ flushHunk();
55
+ flushFile();
56
+ const text = out.join('\n');
57
+ return text && !text.endsWith('\n') ? `${text}\n` : text;
58
+ }
59
+
60
+ module.exports = { filterHunks };
61
+
62
+ if (require.main === module) {
63
+ const pattern = process.argv[2];
64
+ if (!pattern) {
65
+ console.error('usage: git diff -U1 -- file | hunk-filter.js "<regex>"');
66
+ process.exit(2);
67
+ }
68
+ let input = '';
69
+ process.stdin.on('data', (c) => { input += c; });
70
+ process.stdin.on('end', () => {
71
+ process.stdout.write(filterHunks(input, pattern));
72
+ });
73
+ }