atris 3.30.12 → 3.32.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.
- package/AGENTS.md +16 -3
- package/FOR_AGENTS.md +81 -0
- package/README.md +6 -4
- package/atris/CLAUDE.md +8 -0
- package/atris/atris.md +51 -19
- package/atris/skills/README.md +1 -0
- package/atris/skills/blocks/SKILL.md +134 -0
- package/atris/skills/clawhub/philosophy-of-work/SKILL.md +56 -0
- package/atris/skills/youtube/SKILL.md +31 -11
- package/atris.md +15 -0
- package/ax +189 -7
- package/bin/atris.js +273 -225
- package/commands/autoland.js +379 -0
- package/commands/autopilot-front.js +273 -0
- package/commands/autopilot.js +94 -4
- package/commands/business.js +1 -1
- package/commands/clean.js +72 -9
- package/commands/codex-goal.js +72 -22
- package/commands/computer.js +48 -3
- package/commands/gm.js +1 -1
- package/commands/harvest.js +179 -0
- package/commands/init.js +22 -1
- package/commands/land.js +442 -0
- package/commands/loop-front.js +122 -4
- package/commands/member.js +551 -19
- package/commands/mission.js +3674 -278
- package/commands/play.js +1 -1
- package/commands/pulse.js +65 -7
- package/commands/run-front.js +144 -0
- package/commands/run.js +10 -7
- package/commands/sign.js +90 -0
- package/commands/strings.js +301 -0
- package/commands/task.js +782 -108
- package/commands/truth.js +171 -0
- package/commands/xp.js +32 -8
- package/commands/youtube.js +72 -5
- package/decks/README.md +6 -12
- package/lib/auto-accept-certified.js +10 -0
- package/lib/autoland.js +391 -0
- package/lib/context-gatherer.js +0 -8
- package/lib/mission-artifact.js +504 -0
- package/lib/mission-room.js +846 -0
- package/lib/next-moves.js +212 -6
- package/lib/operator-next.js +7 -0
- package/lib/pulse.js +78 -4
- package/lib/runner-command.js +51 -20
- package/lib/runs-prune.js +242 -0
- package/lib/task-db.js +19 -2
- package/lib/task-proof.js +1 -1
- package/package.json +4 -4
- package/decks/atris-seed-pitch-v3.json +0 -118
- package/decks/atris-seed-pitch-v4-skeleton.json +0 -106
- package/decks/atris-seed-pitch-v5.json +0 -109
- package/decks/atris-seed-pitch-v6.json +0 -137
- package/decks/atris-seed-pitch-v7.json +0 -133
- package/decks/mark-pincus-narrative.json +0 -102
- package/decks/mark-pincus-sourcery.json +0 -94
- package/decks/yash-applied-compute-detailed.json +0 -150
- package/decks/yash-applied-compute-generalist.json +0 -82
- package/decks/yash-applied-compute-narrative.json +0 -54
- package/lib/ax-chat-input.js +0 -164
- package/lib/ax-goal.js +0 -307
- package/lib/ax-prefs.js +0 -63
- package/lib/ax-shimmer.js +0 -63
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
function stampIso() {
|
|
7
|
+
return new Date().toISOString();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function toPosixPath(value) {
|
|
11
|
+
return String(value || '').split(path.sep).join('/');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function fileSize(filePath) {
|
|
15
|
+
try {
|
|
16
|
+
return fs.statSync(filePath).size;
|
|
17
|
+
} catch {
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function listFiles(dir) {
|
|
23
|
+
const out = [];
|
|
24
|
+
function visit(current) {
|
|
25
|
+
let entries = [];
|
|
26
|
+
try {
|
|
27
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
28
|
+
} catch {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const fullPath = path.join(current, entry.name);
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
if (entry.name === '_archive') continue;
|
|
35
|
+
visit(fullPath);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (entry.isFile()) out.push(fullPath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
visit(dir);
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function runPathReferences(root) {
|
|
46
|
+
const stateDir = path.join(root, '.atris', 'state');
|
|
47
|
+
const refs = new Set();
|
|
48
|
+
const pattern = /atris\/runs\/[A-Za-z0-9._~:/@%+=,-]+(?:\/[A-Za-z0-9._~:@%+=,-]+)*/g;
|
|
49
|
+
const scan = (filePath) => {
|
|
50
|
+
let text = '';
|
|
51
|
+
try {
|
|
52
|
+
text = fs.readFileSync(filePath, 'utf8');
|
|
53
|
+
} catch {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (const match of text.matchAll(pattern)) {
|
|
57
|
+
refs.add(match[0].replace(/[)"'`.,;]+$/g, ''));
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
if (fs.existsSync(stateDir)) {
|
|
61
|
+
for (const filePath of listFiles(stateDir)) scan(filePath);
|
|
62
|
+
}
|
|
63
|
+
return refs;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function referencedDirs(refs) {
|
|
67
|
+
const dirs = new Set();
|
|
68
|
+
for (const ref of refs) {
|
|
69
|
+
const dir = path.posix.dirname(ref);
|
|
70
|
+
if (dir && dir !== '.' && dir !== 'atris/runs') dirs.add(dir);
|
|
71
|
+
}
|
|
72
|
+
return dirs;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function runEntry(root, filePath, refs, refDirs, nowMs) {
|
|
76
|
+
const rel = toPosixPath(path.relative(root, filePath));
|
|
77
|
+
let stat = null;
|
|
78
|
+
try {
|
|
79
|
+
stat = fs.statSync(filePath);
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const dir = path.posix.dirname(rel);
|
|
84
|
+
const referenced = refs.has(rel) || refDirs.has(dir);
|
|
85
|
+
return {
|
|
86
|
+
path: rel,
|
|
87
|
+
absolute_path: filePath,
|
|
88
|
+
bytes: stat.size,
|
|
89
|
+
mtime_ms: stat.mtimeMs,
|
|
90
|
+
age_days: Math.max(0, Math.floor((nowMs - stat.mtimeMs) / 86400000)),
|
|
91
|
+
referenced,
|
|
92
|
+
kind: path.extname(filePath).toLowerCase().replace(/^\./, '') || 'file',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function compactJsonReceipt(filePath) {
|
|
97
|
+
let parsed = null;
|
|
98
|
+
try {
|
|
99
|
+
parsed = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
schema: parsed.schema || null,
|
|
105
|
+
mission_id: parsed.mission_id || parsed.mission?.id || null,
|
|
106
|
+
objective: parsed.objective || parsed.mission?.objective || null,
|
|
107
|
+
owner: parsed.owner || parsed.mission?.owner || null,
|
|
108
|
+
at: parsed.at || parsed.generated_at || parsed.created_at || null,
|
|
109
|
+
verifier: parsed.verifier || parsed.result?.verifier_result?.command || null,
|
|
110
|
+
passed: parsed.result?.passed === true || parsed.result?.verifier_result?.passed === true || null,
|
|
111
|
+
kind: parsed.result?.kind || parsed.action || null,
|
|
112
|
+
summary: parsed.result?.tick?.summary || parsed.result?.summary || parsed.landing?.happened || null,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function removeEmptyDirs(dir, stopDir) {
|
|
117
|
+
let current = dir;
|
|
118
|
+
while (current && current.startsWith(stopDir) && current !== stopDir) {
|
|
119
|
+
try {
|
|
120
|
+
const entries = fs.readdirSync(current);
|
|
121
|
+
if (entries.length) break;
|
|
122
|
+
fs.rmdirSync(current);
|
|
123
|
+
} catch {
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
current = path.dirname(current);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function pruneRuns(root = process.cwd(), options = {}) {
|
|
131
|
+
const runsDir = options.runsDir || path.join(root, 'atris', 'runs');
|
|
132
|
+
const apply = options.apply === true;
|
|
133
|
+
const archive = options.archive !== false;
|
|
134
|
+
const keepNewest = Number.isFinite(options.keepNewest) ? Math.max(0, Math.floor(options.keepNewest)) : 200;
|
|
135
|
+
const keepDays = Number.isFinite(options.keepDays) ? Math.max(0, Math.floor(options.keepDays)) : 14;
|
|
136
|
+
const nowMs = options.nowMs || Date.now();
|
|
137
|
+
const cutoffMs = nowMs - keepDays * 86400000;
|
|
138
|
+
const refs = runPathReferences(root);
|
|
139
|
+
const refDirs = referencedDirs(refs);
|
|
140
|
+
const files = fs.existsSync(runsDir)
|
|
141
|
+
? listFiles(runsDir).map((filePath) => runEntry(root, filePath, refs, refDirs, nowMs)).filter(Boolean)
|
|
142
|
+
: [];
|
|
143
|
+
const newest = new Set(
|
|
144
|
+
files
|
|
145
|
+
.slice()
|
|
146
|
+
.sort((a, b) => b.mtime_ms - a.mtime_ms || a.path.localeCompare(b.path))
|
|
147
|
+
.slice(0, keepNewest)
|
|
148
|
+
.map((entry) => entry.path),
|
|
149
|
+
);
|
|
150
|
+
const totalBytes = files.reduce((sum, entry) => sum + entry.bytes, 0);
|
|
151
|
+
const decisions = files.map((entry) => {
|
|
152
|
+
const reasons = [];
|
|
153
|
+
if (entry.referenced) reasons.push('referenced');
|
|
154
|
+
if (newest.has(entry.path)) reasons.push('newest');
|
|
155
|
+
if (entry.mtime_ms >= cutoffMs) reasons.push('recent');
|
|
156
|
+
const prune = reasons.length === 0;
|
|
157
|
+
return { ...entry, prune, keep_reasons: reasons };
|
|
158
|
+
});
|
|
159
|
+
const candidates = decisions.filter((entry) => entry.prune);
|
|
160
|
+
const archiveEntries = archive
|
|
161
|
+
? candidates.map((entry) => ({
|
|
162
|
+
path: entry.path,
|
|
163
|
+
bytes: entry.bytes,
|
|
164
|
+
age_days: entry.age_days,
|
|
165
|
+
compact: entry.kind === 'json' ? compactJsonReceipt(entry.absolute_path) : null,
|
|
166
|
+
}))
|
|
167
|
+
: [];
|
|
168
|
+
let manifestPath = null;
|
|
169
|
+
const deleted = [];
|
|
170
|
+
const errors = [];
|
|
171
|
+
if (apply && candidates.length) {
|
|
172
|
+
const archiveDir = path.join(runsDir, '_archive');
|
|
173
|
+
if (archive) {
|
|
174
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
175
|
+
manifestPath = path.join(archiveDir, `prune-${stampIso().replace(/[:.]/g, '-')}.json`);
|
|
176
|
+
fs.writeFileSync(manifestPath, JSON.stringify({
|
|
177
|
+
schema: 'atris.runs_prune_manifest.v1',
|
|
178
|
+
generated_at: stampIso(),
|
|
179
|
+
policy: { keep_newest: keepNewest, keep_days: keepDays },
|
|
180
|
+
pruned_count: candidates.length,
|
|
181
|
+
pruned_bytes: candidates.reduce((sum, entry) => sum + entry.bytes, 0),
|
|
182
|
+
entries: archiveEntries,
|
|
183
|
+
}, null, 2) + '\n', 'utf8');
|
|
184
|
+
}
|
|
185
|
+
for (const entry of candidates) {
|
|
186
|
+
try {
|
|
187
|
+
fs.unlinkSync(entry.absolute_path);
|
|
188
|
+
deleted.push(entry.path);
|
|
189
|
+
removeEmptyDirs(path.dirname(entry.absolute_path), runsDir);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
errors.push({ path: entry.path, error: error.message || String(error) });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
schema: 'atris.runs_prune_preview.v1',
|
|
197
|
+
action: apply ? 'runs_pruned' : 'runs_prune_preview',
|
|
198
|
+
runs_dir: toPosixPath(path.relative(root, runsDir)) || 'atris/runs',
|
|
199
|
+
applied: apply,
|
|
200
|
+
policy: { keep_newest: keepNewest, keep_days: keepDays, archive },
|
|
201
|
+
total_files: files.length,
|
|
202
|
+
total_bytes: totalBytes,
|
|
203
|
+
referenced_files: decisions.filter((entry) => entry.keep_reasons.includes('referenced')).length,
|
|
204
|
+
recent_files: decisions.filter((entry) => entry.keep_reasons.includes('recent')).length,
|
|
205
|
+
newest_files: decisions.filter((entry) => entry.keep_reasons.includes('newest')).length,
|
|
206
|
+
prune_count: candidates.length,
|
|
207
|
+
prune_bytes: candidates.reduce((sum, entry) => sum + entry.bytes, 0),
|
|
208
|
+
deleted_count: deleted.length,
|
|
209
|
+
manifest_path: manifestPath ? toPosixPath(path.relative(root, manifestPath)) : null,
|
|
210
|
+
candidates: candidates.map((entry) => ({
|
|
211
|
+
path: entry.path,
|
|
212
|
+
bytes: entry.bytes,
|
|
213
|
+
age_days: entry.age_days,
|
|
214
|
+
kind: entry.kind,
|
|
215
|
+
})),
|
|
216
|
+
deleted,
|
|
217
|
+
errors,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function formatBytes(bytes) {
|
|
222
|
+
const value = Number(bytes || 0);
|
|
223
|
+
if (value < 1024) return `${value} B`;
|
|
224
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
|
|
225
|
+
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function runsPruneLines(result) {
|
|
229
|
+
return [
|
|
230
|
+
'Landing:',
|
|
231
|
+
` Changed: ${result.applied ? `Pruned ${result.deleted_count} old run file(s).` : `Found ${result.prune_count} old run file(s) eligible for pruning.`}`,
|
|
232
|
+
` How I checked: Scanned ${result.total_files} files in ${result.runs_dir}; kept referenced, newest, and recent proof.`,
|
|
233
|
+
` Proof: ${result.applied ? (result.manifest_path ? `Manifest saved at ${result.manifest_path}.` : 'No manifest was needed.') : `Would reclaim ${formatBytes(result.prune_bytes)}.`}`,
|
|
234
|
+
` Next: ${result.applied ? 'Run this command on a heartbeat when the run folder grows again.' : 'Run again with --apply to delete the eligible old files.'}`,
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
pruneRuns,
|
|
240
|
+
runsPruneLines,
|
|
241
|
+
formatBytes,
|
|
242
|
+
};
|
package/lib/task-db.js
CHANGED
|
@@ -1198,7 +1198,7 @@ function chatTask(db, { id, actor, content, goal, summary }) {
|
|
|
1198
1198
|
};
|
|
1199
1199
|
}
|
|
1200
1200
|
|
|
1201
|
-
function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, careerXpEligible = false, clearedFields = [] }) {
|
|
1201
|
+
function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, careerXpEligible = false, clearedFields = [], landing = {} }) {
|
|
1202
1202
|
if (!id) throw new Error('id required');
|
|
1203
1203
|
const row = getTask(db, id);
|
|
1204
1204
|
if (!row) return { reviewed: false, reason: 'not_found' };
|
|
@@ -1213,6 +1213,15 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1213
1213
|
const clearedReviewFields = Array.isArray(clearedFields)
|
|
1214
1214
|
? Array.from(new Set(clearedFields.filter(field => field === 'lesson' || field === 'next_task')))
|
|
1215
1215
|
: [];
|
|
1216
|
+
const landingInput = landing && typeof landing === 'object' ? landing : {};
|
|
1217
|
+
let landingUpdated = false;
|
|
1218
|
+
for (const key of ['happened', 'checked', 'tested', 'decision']) {
|
|
1219
|
+
const cleaned = cleanLandingText(landingInput[key]);
|
|
1220
|
+
if (cleaned) {
|
|
1221
|
+
metadata[`landing_${key}`] = cleaned;
|
|
1222
|
+
landingUpdated = true;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1216
1225
|
const reviewingPendingProof = row.status === 'review'
|
|
1217
1226
|
&& metadata.approval_status === 'pending'
|
|
1218
1227
|
&& numericReward <= 0
|
|
@@ -1250,7 +1259,7 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1250
1259
|
metadata.accepted_at = new Date().toISOString();
|
|
1251
1260
|
metadata.accepted_by = reviewer;
|
|
1252
1261
|
}
|
|
1253
|
-
if (reviewingPendingProof || updatingPendingReviewProof || (numericReward > 0 && row.status === 'done')) {
|
|
1262
|
+
if (reviewingPendingProof || updatingPendingReviewProof || (numericReward > 0 && row.status === 'done') || landingUpdated) {
|
|
1254
1263
|
withBusyRetry(() => db.prepare(`
|
|
1255
1264
|
UPDATE tasks
|
|
1256
1265
|
SET metadata = ?,
|
|
@@ -1271,6 +1280,14 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1271
1280
|
payload.agent_certified = metadata.agent_certified === true;
|
|
1272
1281
|
payload.agent_certification_policy = metadata.agent_certification_policy || null;
|
|
1273
1282
|
}
|
|
1283
|
+
if (landingUpdated) {
|
|
1284
|
+
payload.landing = {
|
|
1285
|
+
happened: metadata.landing_happened || null,
|
|
1286
|
+
checked: metadata.landing_checked || null,
|
|
1287
|
+
tested: metadata.landing_tested || null,
|
|
1288
|
+
decision: metadata.landing_decision || null,
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1274
1291
|
if (clearedReviewFields.length) payload.cleared_review_fields = clearedReviewFields;
|
|
1275
1292
|
const event = appendTaskEvent(db, {
|
|
1276
1293
|
taskId: id,
|
package/lib/task-proof.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const GENERIC_COMPLETION_PROOF_RE = /^(?:done|done now|complete|completed|finished|fixed|handled|ship|shipped|ok|okay|yes|yep|looks good|looks good to me|all set|should be good|works now|approved|approve|lgtm|failed)$/i;
|
|
4
4
|
|
|
5
|
-
const COMMAND_PROOF_RE = /\b(?:npm\s+run|npm\s+test|node\s+--test|node\s+scripts\/|pnpm\b|yarn\b|npx\b|pytest\b|python\s+-m|tsc\b|vite\s+build|git\s+diff\s+--(?:check|exit-code|quiet)|grep\s+-[A-Za-z]*q[A-Za-z]*|rg\s+(?:-\S+\s+)*(?:"[^"]+"|'[^']+'|\S+)\s+(?:\.{0,2}\/|~\/|\/|[\w.-]+\/|[\w.-]+\.[A-Za-z0-9]|\b(?:atris|bin|commands|lib|scripts|src|test)\b)|diff\s+(?:-u|--brief)|cmp\s+-s|curl\b|atris\s+task|\.\/ax\b|ax\s+--|test\s+-s)\b/i;
|
|
5
|
+
const COMMAND_PROOF_RE = /\b(?:npm\s+run|npm\s+test|node\s+--test|node\s+scripts\/|node\s+bin\/atris[.]js\s+clean\s+--dry-run\s+--json|pnpm\b|yarn\b|npx\b|pytest\b|python\s+-m|tsc\b|vite\s+build|git\s+diff\s+--(?:check|exit-code|quiet)|grep\s+-[A-Za-z]*q[A-Za-z]*|rg\s+(?:-\S+\s+)*(?:"[^"]+"|'[^']+'|\S+)\s+(?:\.{0,2}\/|~\/|\/|[\w.-]+\/|[\w.-]+\.[A-Za-z0-9]|\b(?:atris|bin|commands|lib|scripts|src|test)\b)|diff\s+(?:-u|--brief)|cmp\s+-s|curl\b|atris\s+task|\.\/ax\b|ax\s+--|test\s+-s)\b/i;
|
|
6
6
|
const FILE_PROOF_RE = /(?:^|[\s'"`])(?:\.{0,2}\/|~\/|\/Users\/|src\/|scripts\/|atris\/|backend\/|public\/|resources\/|package[.]json|main[.]js|preload[.]js|AGENTXP_PROOF[.]md)[^\s'"`,;)]*/i;
|
|
7
7
|
const PATH_ONLY_PROOF_RE = /(?:^|[\s'"`])(?:\.{0,2}\/|~\/|\/Users\/|\/private\/|\/var\/|atris\/runs\/|\.atris\/state\/)[^\s'"`,;)]+(?:[.](?:json|jsonl|md|log|txt|png|jpg|jpeg|pdf))?/i;
|
|
8
8
|
const RECEIPT_OR_ARTIFACT_RE = /\b(?:receipt|artifact|screenshot|log|trace|path=|file=|bytes=|model=|opened=|https?:\/\/)\b/i;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atris",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.32.0",
|
|
4
4
|
"main": "bin/atris.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"atris": "bin/atris.js",
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"templates/",
|
|
18
18
|
"README.md",
|
|
19
19
|
"AGENTS.md",
|
|
20
|
+
"FOR_AGENTS.md",
|
|
20
21
|
"atris.md",
|
|
21
22
|
"GETTING_STARTED.md",
|
|
22
23
|
"PERSONA.md",
|
|
23
|
-
"atris/atrisDev.md",
|
|
24
24
|
"atris/CLAUDE.md",
|
|
25
25
|
"atris/GEMINI.md",
|
|
26
26
|
"atris/GETTING_STARTED.md",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
"atris/team/_template/MEMBER.md",
|
|
49
49
|
"atris/features/_templates/",
|
|
50
50
|
"atris/features/company-brain-sync/",
|
|
51
|
-
"templates/",
|
|
52
51
|
"atris/policies/",
|
|
53
52
|
"atris/skills/"
|
|
54
53
|
],
|
|
55
54
|
"scripts": {
|
|
56
55
|
"test": "node --test",
|
|
56
|
+
"lint:decks": "node scripts/lint-all-decks.js",
|
|
57
57
|
"publish:release": "node scripts/publish-atris-release.js",
|
|
58
|
-
"prepare": "cp scripts/pre-commit .git/hooks/pre-commit 2>/dev/null && chmod +x .git/hooks/pre-commit || true"
|
|
58
|
+
"prepare": "cp scripts/pre-commit .git/hooks/pre-commit 2>/dev/null && cp scripts/commit-msg .git/hooks/commit-msg 2>/dev/null && cp scripts/prepare-commit-msg .git/hooks/prepare-commit-msg 2>/dev/null && chmod +x .git/hooks/pre-commit .git/hooks/commit-msg .git/hooks/prepare-commit-msg || true"
|
|
59
59
|
},
|
|
60
60
|
"keywords": [
|
|
61
61
|
"atrisdev",
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"theme": "paper",
|
|
3
|
-
"brand": { "name": "Atris", "accent": "." },
|
|
4
|
-
"slides": [
|
|
5
|
-
{
|
|
6
|
-
"type": "title",
|
|
7
|
-
"headline": "The self-improving **business computer.**",
|
|
8
|
-
"sub": "Work closes its own loop. Memory, authority, receipts, outcomes. One standard for humans and agents.",
|
|
9
|
-
"panel": {
|
|
10
|
-
"header": { "title": "Closed loop", "meta": "every action" },
|
|
11
|
-
"rows": [
|
|
12
|
-
{ "title": "context", "sub": "memory in", "value": "1", "valueSub": "step", "sev": 2 },
|
|
13
|
-
{ "title": "action", "sub": "member acts", "value": "2", "valueSub": "step", "sev": 1 },
|
|
14
|
-
{ "title": "receipt", "sub": "proof out", "value": "3", "valueSub": "step", "sev": 0, "active": true },
|
|
15
|
-
{ "title": "outcome", "sub": "result", "value": "4", "valueSub": "step", "sev": 2 }
|
|
16
|
-
],
|
|
17
|
-
"footer": { "left": "environment first", "right": "model later" }
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"type": "statement",
|
|
22
|
-
"text": "Work used to **end.** Now every action can become memory.",
|
|
23
|
-
"sub": "Stored work becomes acted work, then remembered work. Context, action, receipt, outcome, reward, better next action."
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"type": "columns",
|
|
27
|
-
"heading": "A business computer, not a chatbot",
|
|
28
|
-
"columns": [
|
|
29
|
-
{
|
|
30
|
-
"h": "Memory",
|
|
31
|
-
"b": "Receipts compress into lessons and return as minimum useful context."
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"h": "Members",
|
|
35
|
-
"b": "Humans and agents with owner, tools, authority, trail, and score."
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"h": "Receipts",
|
|
39
|
-
"b": "Who authorized, who acted, what proof confirms it, what the business got."
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"type": "statement",
|
|
45
|
-
"text": "They learn the **click.** We learn the outcome.",
|
|
46
|
-
"sub": "Others reward the draft interaction. Atris rewards the business result: reply, booking, deal, recovery."
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"type": "panel",
|
|
50
|
-
"heading": "The market proved the gap.",
|
|
51
|
-
"sub": "Agents act everywhere. Almost none verify the result.",
|
|
52
|
-
"panel": {
|
|
53
|
-
"header": { "title": "Why now", "meta": "2026" },
|
|
54
|
-
"rows": [
|
|
55
|
-
{ "title": "No verification", "sub": "AIRQ audit", "value": "98%", "valueSub": "of agents", "sev": 0, "active": true },
|
|
56
|
-
{ "title": "Self-grader cheats", "sub": "Reward benchmark", "value": "14%", "valueSub": "top models", "sev": 0 },
|
|
57
|
-
{ "title": "Agent rollback", "sub": "Sinch survey", "value": "74%", "valueSub": "enterprises", "sev": 1 }
|
|
58
|
-
],
|
|
59
|
-
"footer": { "left": "guardrails gate behavior", "right": "not results" }
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"type": "columns",
|
|
64
|
-
"heading": "Product today",
|
|
65
|
-
"columns": [
|
|
66
|
-
{
|
|
67
|
-
"h": "Atris2 Fast",
|
|
68
|
-
"b": "Open tool harness. Periphery prepares work without usurping judgment."
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"h": "Deferral queue",
|
|
72
|
-
"b": "Sends, money, and public acts pause for your approval with a judgment packet."
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"h": "Antislop gates",
|
|
76
|
-
"b": "Deterministic block on AI UI tells, hype copy, and raw outbound artifacts."
|
|
77
|
-
}
|
|
78
|
-
]
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"type": "bignumber",
|
|
82
|
-
"number": "+3.35",
|
|
83
|
-
"label": "RL readiness lift after verified episodes",
|
|
84
|
-
"sub": "Diff, receipt, verifier, outcome. Atris runs on Atris."
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"type": "panel",
|
|
88
|
-
"heading": "Customer recovery first.",
|
|
89
|
-
"sub": "Close one painful loop. Prove the outcome. Expand.",
|
|
90
|
-
"panel": {
|
|
91
|
-
"header": { "title": "Wedge", "meta": "expand" },
|
|
92
|
-
"rows": [
|
|
93
|
-
{ "title": "Customer silent", "sub": "churn or complaint", "value": "in", "sev": 1 },
|
|
94
|
-
{ "title": "Member acts", "sub": "draft recovery", "value": "act", "sev": 0, "active": true },
|
|
95
|
-
{ "title": "Receipt", "sub": "trust or revenue?", "value": "proof", "sev": 2 },
|
|
96
|
-
{ "title": "Expand", "sub": "sales, ops, finance", "value": "out", "sev": 1 }
|
|
97
|
-
],
|
|
98
|
-
"footer": { "left": "one loop proven", "right": "then expand" }
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"type": "chips",
|
|
103
|
-
"heading": "Business model",
|
|
104
|
-
"sub": "We do not tax Members. Members close loops.",
|
|
105
|
-
"chips": ["$200/mo computer", "Unlimited Members", "Usage credits", "Managed setup", "Enterprise"],
|
|
106
|
-
"mono": "base + verified outcomes"
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"type": "close",
|
|
110
|
-
"tagline": "Ambition and freedom should not cancel each other out.",
|
|
111
|
-
"buttons": [
|
|
112
|
-
{ "label": "See the demo", "primary": true },
|
|
113
|
-
{ "label": "Talk to us" }
|
|
114
|
-
],
|
|
115
|
-
"footer": "Raising $10M seed · atris.ai · 2026"
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"theme": "paper",
|
|
3
|
-
"brand": { "name": "Atris", "accent": "." },
|
|
4
|
-
"slides": [
|
|
5
|
-
{
|
|
6
|
-
"type": "columns",
|
|
7
|
-
"heading": "1 · The gate",
|
|
8
|
-
"sub": "Models regulated, access unequal, AI narrative toxic.",
|
|
9
|
-
"columns": [
|
|
10
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
11
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
12
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
13
|
-
]
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"type": "columns",
|
|
17
|
-
"heading": "2 · The trap",
|
|
18
|
-
"sub": "Everyone is building the same mimetic slop on rented intelligence.",
|
|
19
|
-
"columns": [
|
|
20
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
21
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
22
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
23
|
-
]
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"type": "columns",
|
|
27
|
-
"heading": "3 · The shift",
|
|
28
|
-
"sub": "Early adopters want an owned center, not another chatbot.",
|
|
29
|
-
"columns": [
|
|
30
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
31
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
32
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"type": "columns",
|
|
37
|
-
"heading": "4 · The sovereign individual",
|
|
38
|
-
"sub": "At the center. Ecosystem around them — software, school, community, capital.",
|
|
39
|
-
"columns": [
|
|
40
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
41
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
42
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
43
|
-
]
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"type": "columns",
|
|
47
|
-
"heading": "5 · The product",
|
|
48
|
-
"sub": "Self-improving environment, swappable models, agent-native system of record.",
|
|
49
|
-
"columns": [
|
|
50
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
51
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
52
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
53
|
-
]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"type": "columns",
|
|
57
|
-
"heading": "6 · The proof",
|
|
58
|
-
"sub": "Center Study and businesses that improve overnight. Live loops, not demos.",
|
|
59
|
-
"columns": [
|
|
60
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
61
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
62
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"type": "columns",
|
|
67
|
-
"heading": "7 · First business",
|
|
68
|
-
"sub": "Education / transformation. ~$250k run rate. 1–3 FDEs per cluster.",
|
|
69
|
-
"columns": [
|
|
70
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
71
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
72
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
73
|
-
]
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
"type": "columns",
|
|
77
|
-
"heading": "8 · Customers",
|
|
78
|
-
"sub": "DoorDash and Pallet — what actually runs today.",
|
|
79
|
-
"columns": [
|
|
80
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
81
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
82
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
83
|
-
]
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
"type": "columns",
|
|
87
|
-
"heading": "9 · Growth",
|
|
88
|
-
"sub": "Founder-first distribution. Mimetic spread. Clone the machine.",
|
|
89
|
-
"columns": [
|
|
90
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
91
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
92
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
93
|
-
]
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
"type": "columns",
|
|
97
|
-
"heading": "10 · The ask",
|
|
98
|
-
"sub": "$10M — FDE team, narrative, run more businesses, own the layer beneath the gate.",
|
|
99
|
-
"columns": [
|
|
100
|
-
{ "h": "bullet 1", "b": "(your words)" },
|
|
101
|
-
{ "h": "bullet 2", "b": "(your words)" },
|
|
102
|
-
{ "h": "bullet 3", "b": "(your words)" }
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"theme": "paper",
|
|
3
|
-
"brand": { "name": "Atris", "accent": "." },
|
|
4
|
-
"slides": [
|
|
5
|
-
{
|
|
6
|
-
"type": "title",
|
|
7
|
-
"headline": "Every business owner has two real problems.",
|
|
8
|
-
"sub": "The work they hate doing. The work they can't afford to hire for. Atris does both — inside their company, with a receipt every time.",
|
|
9
|
-
"panel": {
|
|
10
|
-
"header": { "title": "Closed loop", "meta": "every action" },
|
|
11
|
-
"rows": [
|
|
12
|
-
{ "title": "context", "sub": "memory in", "value": "1", "valueSub": "step", "sev": 2 },
|
|
13
|
-
{ "title": "action", "sub": "member acts", "value": "2", "valueSub": "step", "sev": 1 },
|
|
14
|
-
{ "title": "receipt", "sub": "proof out", "value": "3", "valueSub": "step", "sev": 0, "active": true },
|
|
15
|
-
{ "title": "outcome", "sub": "result", "value": "4", "valueSub": "step", "sev": 2 }
|
|
16
|
-
],
|
|
17
|
-
"footer": { "left": "perimeter-resident", "right": "outcome-graded" }
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"type": "columns",
|
|
22
|
-
"heading": "Three operators. Three jobs. One product.",
|
|
23
|
-
"columns": [
|
|
24
|
-
{
|
|
25
|
-
"h": "DoorDash",
|
|
26
|
-
"b": "Forecasting, weekly business review, internal Atris adoption. The workflow became a process. The process became a religion."
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"h": "Pallet",
|
|
30
|
-
"b": "Recruiting team. Atris learns the non-engineering workflow and converts it to a coding problem."
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"h": "[Customer 3]",
|
|
34
|
-
"b": "Bookkeeping or finance ops. Hours of human grunt work compressed to minutes, with a receipt per close."
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"type": "bignumber",
|
|
40
|
-
"number": "$250k",
|
|
41
|
-
"label": "run rate · 1–3 FDEs · operator workflows at $10M–$5B companies",
|
|
42
|
-
"sub": "We start in the room nobody else is in. Then ten more rooms exactly like it."
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"type": "statement",
|
|
46
|
-
"text": "They store **facts.** We learn the **outcome.**",
|
|
47
|
-
"sub": "Mem0 stores facts. Letta stores context. Glean indexes docs. Atris is the only one where the customer's runtime ships back a reward signal so the agent gets measurably better at their work — with the data never leaving their perimeter."
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"type": "panel",
|
|
51
|
-
"heading": "One machine, N customers.",
|
|
52
|
-
"sub": "Each with their own disk, own behavior, own reward signal. Same code everywhere. No data crosses.",
|
|
53
|
-
"panel": {
|
|
54
|
-
"header": { "title": "Architecture", "meta": "perimeter-resident" },
|
|
55
|
-
"rows": [
|
|
56
|
-
{ "title": "Disk", "sub": "per-customer memory", "value": "in", "valueSub": "perimeter", "sev": 1 },
|
|
57
|
-
{ "title": "Behavior", "sub": "per-customer policies", "value": "in", "valueSub": "perimeter", "sev": 1 },
|
|
58
|
-
{ "title": "Reward signal", "sub": "verifiable outcomes", "value": "out", "valueSub": "to us", "sev": 0, "active": true },
|
|
59
|
-
{ "title": "Weights", "sub": "trained on reward stream", "value": "back", "valueSub": "each release", "sev": 2 }
|
|
60
|
-
],
|
|
61
|
-
"footer": { "left": "data plane stays", "right": "reward plane streams" }
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"type": "statement",
|
|
66
|
-
"text": "The labs are becoming the new **oil companies.**",
|
|
67
|
-
"sub": "Frontier models are being rate-limited, regulated, gated customer-by-customer. Standard Oil didn't lose to a better well — it lost to the refinery. The next trillion-dollar company owns the layer between raw intelligence and the work."
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"type": "columns",
|
|
71
|
-
"heading": "Why now",
|
|
72
|
-
"columns": [
|
|
73
|
-
{
|
|
74
|
-
"h": "Labs gated",
|
|
75
|
-
"b": "Tokens regulated. Frontier access limited. Customer-by-customer approval. The race for the smartest brain is becoming a utility."
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"h": "Wrappers dead",
|
|
79
|
-
"b": "Thin GPT wrappers are over. What's alive is the layer beneath — memory, taste, approval, proof, on the customer's perimeter."
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"h": "Window open",
|
|
83
|
-
"b": "Installation phase. History says the next decade's winners are not the rail-layers. Amazon over Cisco. Google over WorldCom. Walmart over the railroads."
|
|
84
|
-
}
|
|
85
|
-
]
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
"type": "statement",
|
|
89
|
-
"text": "The **Shadow Center.**",
|
|
90
|
-
"sub": "Every system has a center. The labs occupy the one beneath every AI-native business today. The seat is open. Atris is the architecture for the next occupant — memory, taste, approval, proof, running inside the customer's perimeter, getting sharper every week."
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
"type": "chips",
|
|
94
|
-
"heading": "Business model",
|
|
95
|
-
"sub": "Base + services + outcomes. We do not tax Members.",
|
|
96
|
-
"chips": ["$200/mo computer", "Unlimited Members", "$5–25k/mo FDE-embedded", "Outcome upside", "Enterprise"],
|
|
97
|
-
"mono": "Sierra-shaped: 18 months behind their arc"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"type": "close",
|
|
101
|
-
"tagline": "In 2030, every serious AI business runs on a Shadow Center. We are the one underneath.",
|
|
102
|
-
"buttons": [
|
|
103
|
-
{ "label": "See the demo", "primary": true },
|
|
104
|
-
{ "label": "Talk to us" }
|
|
105
|
-
],
|
|
106
|
-
"footer": "Raising $10M seed · atris.ai · 2026"
|
|
107
|
-
}
|
|
108
|
-
]
|
|
109
|
-
}
|