atris 3.15.13 → 3.15.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/AGENTS.md +84 -8
  2. package/README.md +5 -1
  3. package/atris/AGENTS.md +46 -1
  4. package/atris/CLAUDE.md +36 -1
  5. package/atris/GEMINI.md +14 -1
  6. package/atris/atris.md +12 -1
  7. package/atris/atrisDev.md +3 -2
  8. package/atris/context/README.md +11 -0
  9. package/atris/features/company-brain-sync/validate.md +5 -5
  10. package/atris/learnings.jsonl +1 -0
  11. package/atris/policies/atris-design.md +2 -0
  12. package/atris/skills/aeo/SKILL.md +2 -2
  13. package/atris/skills/atris/SKILL.md +15 -62
  14. package/atris/skills/design/SKILL.md +2 -0
  15. package/atris/skills/imessage/SKILL.md +19 -2
  16. package/atris/skills/loop/SKILL.md +6 -5
  17. package/atris/skills/magic-inbox/SKILL.md +1 -1
  18. package/atris/team/_template/MEMBER.md +23 -1
  19. package/atris/team/brainstormer/START_HERE.md +6 -0
  20. package/atris/team/executor/MEMBER.md +13 -0
  21. package/atris/team/executor/START_HERE.md +6 -0
  22. package/atris/team/launcher/START_HERE.md +6 -0
  23. package/atris/team/mission-lead/MEMBER.md +39 -0
  24. package/atris/team/mission-lead/MISSION.md +33 -0
  25. package/atris/team/mission-lead/START_HERE.md +6 -0
  26. package/atris/team/navigator/MEMBER.md +11 -0
  27. package/atris/team/navigator/START_HERE.md +6 -0
  28. package/atris/team/opus-overnight/MEMBER.md +39 -0
  29. package/atris/team/opus-overnight/MISSION.md +61 -0
  30. package/atris/team/opus-overnight/START_HERE.md +6 -0
  31. package/atris/team/opus-overnight/STEERING.md +35 -0
  32. package/atris/team/researcher/START_HERE.md +6 -0
  33. package/atris/team/validator/MEMBER.md +26 -6
  34. package/atris/team/validator/START_HERE.md +6 -0
  35. package/atris/wiki/concepts/agent-activation-contract.md +79 -0
  36. package/atris/wiki/concepts/workspace-initialization-contract.md +73 -0
  37. package/atris/wiki/index.md +27 -0
  38. package/atris/wiki/sources/atris-labs-2026-05-10.txt +17 -0
  39. package/atris/wiki/sources/atris-labs-goals-2026-05-10.txt +15 -0
  40. package/atris/wiki/sources/atrisos-generative-ui-product-surface-2026-05-10.txt +10 -0
  41. package/atris/wiki/sources/jack-dorsey-2026-05-10.txt +12 -0
  42. package/atris.md +49 -13
  43. package/bin/atris.js +660 -22
  44. package/commands/activate.js +12 -3
  45. package/commands/aeo.js +1 -1
  46. package/commands/align.js +10 -10
  47. package/commands/analytics.js +9 -4
  48. package/commands/app.js +2 -0
  49. package/commands/apps.js +276 -0
  50. package/commands/auth.js +1 -1
  51. package/commands/autopilot.js +74 -5
  52. package/commands/brain.js +536 -61
  53. package/commands/brainstorm.js +12 -12
  54. package/commands/business-sync.js +142 -24
  55. package/commands/clean.js +9 -6
  56. package/commands/codex-goal.js +311 -0
  57. package/commands/errors.js +11 -1
  58. package/commands/feedback.js +55 -17
  59. package/commands/fork.js +2 -2
  60. package/commands/gm.js +376 -0
  61. package/commands/init.js +80 -3
  62. package/commands/integrations.js +524 -0
  63. package/commands/learn.js +25 -16
  64. package/commands/lesson.js +41 -0
  65. package/commands/lifecycle.js +2 -2
  66. package/commands/member.js +2416 -9
  67. package/commands/mission.js +1776 -0
  68. package/commands/now.js +48 -7
  69. package/commands/play.js +425 -0
  70. package/commands/publish.js +2 -1
  71. package/commands/pull.js +72 -29
  72. package/commands/push.js +199 -17
  73. package/commands/review.js +51 -13
  74. package/commands/skill.js +2 -2
  75. package/commands/soul.js +19 -13
  76. package/commands/status.js +6 -1
  77. package/commands/sync.js +5 -4
  78. package/commands/task.js +1041 -147
  79. package/commands/terminal.js +5 -5
  80. package/commands/verify.js +7 -5
  81. package/commands/visualize.js +7 -0
  82. package/commands/wiki.js +53 -16
  83. package/commands/workflow.js +298 -54
  84. package/commands/workspace-clean.js +1 -1
  85. package/commands/worktree.js +468 -0
  86. package/commands/xp.js +1608 -0
  87. package/lib/manifest.js +34 -4
  88. package/lib/scorecard.js +3 -2
  89. package/lib/task-db.js +408 -27
  90. package/lib/todo-fallback.js +28 -2
  91. package/lib/todo.js +5 -3
  92. package/package.json +23 -2
  93. package/utils/update-check.js +51 -1
package/commands/gm.js ADDED
@@ -0,0 +1,376 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+
7
+ const ROLE_PLAYERS_TO_IGNORE = new Set([
8
+ 'game-manager',
9
+ 'navigator',
10
+ 'executor',
11
+ 'validator',
12
+ 'launcher',
13
+ 'researcher',
14
+ 'brainstormer',
15
+ 'ops',
16
+ ]);
17
+
18
+ function showHelp() {
19
+ console.log('');
20
+ console.log('Usage: atris gm [--manager <id>] [--player <id>] [--workspace <path>] [--json]');
21
+ console.log('');
22
+ console.log('Description:');
23
+ console.log(' Enter AgentXP General Manager mode for the current Atris workspace.');
24
+ console.log(' Shows local players, active missions, review queue, and the next command');
25
+ console.log(' that moves the same AgentXP game loop forward.');
26
+ console.log('');
27
+ console.log('Options:');
28
+ console.log(' --manager <id> Manager id. Defaults to game-manager when present.');
29
+ console.log(' --as <id> Alias for --manager.');
30
+ console.log(' --player <id> Preferred player when seeding a first local mission.');
31
+ console.log(' --workspace <p> Read missions from another Atris workspace.');
32
+ console.log(' --no-seed Do not create a starter player mission.');
33
+ console.log(' --json Print machine-readable mode state.');
34
+ console.log(' --help, -h Show this help.');
35
+ console.log('');
36
+ }
37
+
38
+ function flag(args, name) {
39
+ const inline = args.find(arg => arg.startsWith(`${name}=`));
40
+ if (inline) return inline.slice(name.length + 1);
41
+ const index = args.indexOf(name);
42
+ if (index >= 0 && args[index + 1] && !args[index + 1].startsWith('--')) {
43
+ return args[index + 1];
44
+ }
45
+ return null;
46
+ }
47
+
48
+ function hasFlag(args, name) {
49
+ return args.includes(name) || args.some(arg => arg.startsWith(`${name}=`));
50
+ }
51
+
52
+ function positional(args) {
53
+ return args.filter((arg, index) => {
54
+ if (arg.startsWith('--')) return false;
55
+ if (index > 0 && args[index - 1].startsWith('--')) return false;
56
+ return true;
57
+ });
58
+ }
59
+
60
+ function slugify(value) {
61
+ return String(value || '')
62
+ .trim()
63
+ .toLowerCase()
64
+ .replace(/@.*$/, '')
65
+ .replace(/[^a-z0-9]+/g, '-')
66
+ .replace(/^-+|-+$/g, '');
67
+ }
68
+
69
+ function taskRef(task) {
70
+ return task.display_id || task.legacy_ref || String(task.id || '').slice(0, 8);
71
+ }
72
+
73
+ function taskAssignee(task) {
74
+ const metadata = task && task.metadata && typeof task.metadata === 'object'
75
+ ? task.metadata
76
+ : {};
77
+ return metadata.assigned_to
78
+ || metadata.owner
79
+ || metadata.assignee
80
+ || task.claimed_by
81
+ || null;
82
+ }
83
+
84
+ function clip(value, max = 240) {
85
+ const text = String(value || '').replace(/\s+/g, ' ').trim();
86
+ if (text.length <= max) return text;
87
+ return `${text.slice(0, Math.max(0, max - 3)).trim()}...`;
88
+ }
89
+
90
+ function teamMembers(workspaceRoot) {
91
+ const teamDir = path.join(workspaceRoot, 'atris', 'team');
92
+ try {
93
+ return fs.readdirSync(teamDir, { withFileTypes: true })
94
+ .filter(entry => entry.isDirectory())
95
+ .map(entry => slugify(entry.name))
96
+ .filter(Boolean)
97
+ .filter(name => !name.startsWith('_') && name !== 'template')
98
+ .filter(name => fs.existsSync(path.join(teamDir, name, 'MEMBER.md')) || fs.existsSync(path.join(teamDir, name, 'START_HERE.md')));
99
+ } catch {
100
+ return [];
101
+ }
102
+ }
103
+
104
+ function inferManager(workspaceRoot, args = []) {
105
+ const explicit = flag(args, '--manager') || flag(args, '--as') || positional(args)[0];
106
+ if (explicit) return { manager: slugify(explicit), source: 'flag' };
107
+
108
+ for (const value of [process.env.ATRIS_GM, process.env.ATRIS_MANAGER, process.env.ATRIS_AGENT_ID]) {
109
+ const manager = slugify(value);
110
+ if (manager) return { manager, source: 'env' };
111
+ }
112
+
113
+ if (fs.existsSync(path.join(workspaceRoot, 'atris', 'team', 'game-manager'))) {
114
+ return { manager: 'game-manager', source: 'team' };
115
+ }
116
+
117
+ return { manager: 'game-manager', source: 'default' };
118
+ }
119
+
120
+ function activeTasks(tasks) {
121
+ return (tasks || []).filter(task => !['done', 'failed'].includes(task.status));
122
+ }
123
+
124
+ function activeAgentXpTasks(tasks) {
125
+ return activeTasks(tasks).filter((task) => {
126
+ const metadata = task.metadata || {};
127
+ const text = `${task.title || ''} ${task.tag || ''} ${metadata.delegate_via || ''}`.toLowerCase();
128
+ return text.includes('agentxp') || text.includes('agent-xp');
129
+ });
130
+ }
131
+
132
+ function playersFromTasks(tasks) {
133
+ const players = new Set();
134
+ for (const task of activeTasks(tasks)) {
135
+ const assignee = slugify(taskAssignee(task));
136
+ if (assignee && !ROLE_PLAYERS_TO_IGNORE.has(assignee)) players.add(assignee);
137
+ const claimedBy = slugify(task.claimed_by);
138
+ if (claimedBy && !ROLE_PLAYERS_TO_IGNORE.has(claimedBy)) players.add(claimedBy);
139
+ }
140
+ return Array.from(players).sort();
141
+ }
142
+
143
+ function playersFromWorkspace(workspaceRoot) {
144
+ return teamMembers(workspaceRoot)
145
+ .filter(member => !ROLE_PLAYERS_TO_IGNORE.has(member))
146
+ .sort();
147
+ }
148
+
149
+ function starterMissionTitle() {
150
+ return 'AgentXP Mode first rep: complete one proof-backed customer-motion mission';
151
+ }
152
+
153
+ function starterMissionPrompt(player) {
154
+ return [
155
+ `Player ${player}: enter AgentXP Mode in this local workspace.`,
156
+ 'Pick one concrete customer-motion rep you can finish today.',
157
+ 'Use an agent for the artifact and verifier proof.',
158
+ 'Human accept/revise gates the XP.',
159
+ ].join(' ');
160
+ }
161
+
162
+ function pickSeedPlayer(workspaceRoot, tasks, args = []) {
163
+ const explicit = flag(args, '--player') || flag(args, '--user');
164
+ if (explicit) return slugify(explicit);
165
+
166
+ const fromTasks = playersFromTasks(tasks);
167
+ if (fromTasks.length === 1) return fromTasks[0];
168
+
169
+ const fromWorkspace = playersFromWorkspace(workspaceRoot);
170
+ if (fromWorkspace.length === 1) return fromWorkspace[0];
171
+
172
+ const local = slugify(process.env.ATRIS_PLAYER || process.env.USER || os.userInfo().username);
173
+ if (local && !ROLE_PLAYERS_TO_IGNORE.has(local)) return local;
174
+
175
+ return null;
176
+ }
177
+
178
+ function ensureStarterMission(taskDb, db, workspaceRoot, tasks, args = []) {
179
+ if (hasFlag(args, '--no-seed')) return { tasks, seeded: null };
180
+ if (!fs.existsSync(path.join(workspaceRoot, 'atris'))) return { tasks, seeded: null };
181
+ if (activeAgentXpTasks(tasks).length) return { tasks, seeded: null };
182
+
183
+ const player = pickSeedPlayer(workspaceRoot, tasks, args);
184
+ if (!player) return { tasks, seeded: null };
185
+
186
+ const result = taskDb.addTask(db, {
187
+ title: starterMissionTitle(),
188
+ tag: 'agent-xp',
189
+ workspaceRoot,
190
+ metadata: {
191
+ assigned_to: player,
192
+ delegate_via: 'agentxp_gm',
193
+ auto_seeded_by: 'atris gm',
194
+ created_for_day: new Date().toISOString().slice(0, 10),
195
+ },
196
+ });
197
+ taskDb.noteTask(db, {
198
+ id: result.id,
199
+ actor: 'game-manager',
200
+ content: starterMissionPrompt(player),
201
+ });
202
+
203
+ const refreshed = taskDb.withTaskDisplayRefs(taskDb.listTasks(db, {
204
+ workspaceRoot,
205
+ limit: 500,
206
+ }));
207
+ return {
208
+ tasks: refreshed,
209
+ seeded: refreshed.find(task => task.id === result.id) || null,
210
+ };
211
+ }
212
+
213
+ function groupPlayers(tasks, workspaceRoot) {
214
+ const players = new Map();
215
+ for (const task of activeTasks(tasks)) {
216
+ const player = slugify(taskAssignee(task)) || 'unassigned';
217
+ if (!players.has(player)) {
218
+ players.set(player, {
219
+ player,
220
+ source: 'task',
221
+ open: 0,
222
+ claimed: 0,
223
+ review: 0,
224
+ active: 0,
225
+ });
226
+ }
227
+ const row = players.get(player);
228
+ row.active += 1;
229
+ if (task.status === 'open') row.open += 1;
230
+ if (task.status === 'claimed') row.claimed += 1;
231
+ if (task.status === 'review') row.review += 1;
232
+ }
233
+
234
+ if (!players.size) {
235
+ for (const player of playersFromWorkspace(workspaceRoot)) {
236
+ players.set(player, {
237
+ player,
238
+ source: 'team',
239
+ open: 0,
240
+ claimed: 0,
241
+ review: 0,
242
+ active: 0,
243
+ });
244
+ }
245
+ }
246
+
247
+ return Array.from(players.values())
248
+ .filter(row => !ROLE_PLAYERS_TO_IGNORE.has(row.player))
249
+ .sort((a, b) => b.active - a.active || a.player.localeCompare(b.player));
250
+ }
251
+
252
+ function compactTask(task) {
253
+ if (!task) return null;
254
+ return {
255
+ id: task.id,
256
+ ref: taskRef(task),
257
+ title: task.title,
258
+ status: task.status,
259
+ assigned_to: taskAssignee(task),
260
+ claimed_by: task.claimed_by || null,
261
+ };
262
+ }
263
+
264
+ function nextCommands({ seeded, reviewQueue, missions, players }) {
265
+ if (reviewQueue.length) {
266
+ const ref = reviewQueue[0].ref;
267
+ return [
268
+ `atris task show ${ref}`,
269
+ `atris task accept ${ref} --proof "<human review>"`,
270
+ `atris task revise ${ref} --note "<what must change>"`,
271
+ ];
272
+ }
273
+ if (missions.length) {
274
+ const mission = missions[0];
275
+ const player = mission.assigned_to || mission.claimed_by || players[0]?.player || 'player';
276
+ if (mission.status === 'open') return [`atris task claim ${mission.ref} --as ${player}`];
277
+ return [`atris play --as ${player}`];
278
+ }
279
+ if (seeded) return [`atris play --as ${seeded.assigned_to || 'player'}`];
280
+ return ['atris gm --player <player>'];
281
+ }
282
+
283
+ function gmState(args = []) {
284
+ const taskDb = require('../lib/task-db');
285
+ const workspaceArg = flag(args, '--workspace') || flag(args, '--root') || process.cwd();
286
+ const workspaceRoot = taskDb.workspaceRoot(path.resolve(workspaceArg));
287
+ const db = taskDb.open();
288
+ let tasks = taskDb.withTaskDisplayRefs(taskDb.listTasks(db, {
289
+ workspaceRoot,
290
+ limit: 500,
291
+ }));
292
+ const detected = inferManager(workspaceRoot, args);
293
+ const starter = ensureStarterMission(taskDb, db, workspaceRoot, tasks, args);
294
+ tasks = starter.tasks;
295
+
296
+ const missions = activeAgentXpTasks(tasks).map(compactTask);
297
+ const reviewQueue = missions.filter(task => task.status === 'review');
298
+ const players = groupPlayers(tasks, workspaceRoot);
299
+ const seeded = compactTask(starter.seeded);
300
+ const commands = nextCommands({ seeded, reviewQueue, missions, players });
301
+
302
+ return {
303
+ schema: 'atris.agentxp_gm_mode.v1',
304
+ mode: 'AgentXP General Manager',
305
+ generated_at: new Date().toISOString(),
306
+ manager: detected.manager,
307
+ manager_source: detected.source,
308
+ workspace_root: workspaceRoot,
309
+ workspace_name: path.basename(workspaceRoot),
310
+ seeded,
311
+ counts: {
312
+ players: players.length,
313
+ missions: missions.length,
314
+ review: reviewQueue.length,
315
+ },
316
+ players,
317
+ missions,
318
+ review_queue: reviewQueue,
319
+ next_commands: commands,
320
+ xp_rule: 'GM can route missions and review proof, but AgentXP still lands only after human accept.',
321
+ };
322
+ }
323
+
324
+ function render(state) {
325
+ console.log('');
326
+ console.log('AgentXP General Manager');
327
+ console.log(`Manager ${state.manager} | Workspace ${state.workspace_name}`);
328
+ console.log('');
329
+
330
+ if (state.seeded) {
331
+ console.log(`Starter mission created locally: ${state.seeded.ref} -> ${state.seeded.assigned_to || 'player'}`);
332
+ console.log('');
333
+ }
334
+
335
+ console.log(`Players ${state.counts.players} | Missions ${state.counts.missions} | Review ${state.counts.review}`);
336
+ if (state.players.length) {
337
+ console.log('');
338
+ console.log('Players:');
339
+ for (const player of state.players.slice(0, 8)) {
340
+ console.log(`- ${player.player}: ${player.active} active, ${player.review} review`);
341
+ }
342
+ }
343
+
344
+ if (state.missions.length) {
345
+ console.log('');
346
+ console.log('Missions:');
347
+ for (const task of state.missions.slice(0, 8)) {
348
+ console.log(`- ${task.ref} [${task.status}] ${task.assigned_to || 'unassigned'}: ${clip(task.title, 120)}`);
349
+ }
350
+ }
351
+
352
+ console.log('');
353
+ console.log('XP rule: no proof, no AgentXP; accept/revise stays human-gated.');
354
+ console.log('');
355
+ console.log('Next commands:');
356
+ for (const command of state.next_commands) console.log(`- ${command}`);
357
+ }
358
+
359
+ async function gmCommand(...args) {
360
+ if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
361
+ showHelp();
362
+ return;
363
+ }
364
+
365
+ const state = gmState(args);
366
+ if (hasFlag(args, '--json')) {
367
+ console.log(JSON.stringify(state, null, 2));
368
+ return;
369
+ }
370
+ render(state);
371
+ }
372
+
373
+ module.exports = {
374
+ gmCommand,
375
+ gmState,
376
+ };
package/commands/init.js CHANGED
@@ -233,6 +233,17 @@ ${profile.hasCode ? `**Validation:** Run \`${profile.testCommand}\` to verify ch
233
233
  }
234
234
 
235
235
  function initAtris() {
236
+ // Print usage on -h / --help / help instead of running init (which scaffolds
237
+ // many files, including atris/now.md and atris/team/). Asking for help
238
+ // shouldn't have file-system side effects.
239
+ const args = process.argv.slice(3);
240
+ if (args[0] === '-h' || args[0] === '--help' || args[0] === 'help') {
241
+ console.log('Usage: atris init [--force]');
242
+ console.log('');
243
+ console.log(' Scaffold the atris/ workspace in the current directory.');
244
+ console.log(' Refuses to run inside an existing atris/ folder unless --force is passed.');
245
+ return;
246
+ }
236
247
  // GUARD: Refuse nested init.
237
248
  // Bug: running `atris init` inside an existing `atris/` folder creates
238
249
  // `atris/atris/` nesting hell. Cloud doordash had this exact problem.
@@ -595,7 +606,7 @@ tools: []
595
606
  // Create agent instruction files for different tools
596
607
  const agentInstructions = `# AGENTS.md — Universal Agent Instructions
597
608
 
598
- > Works with: Claude Code, Cursor, Codex, Windsurf, and any AI coding agent.
609
+ > Works with: Claude Code, Cursor, Codex, OpenClaw, Windsurf, and any AI coding agent.
599
610
 
600
611
  ## FIRST MESSAGE — Boot Sequence
601
612
 
@@ -609,14 +620,46 @@ This is the Atris boot sequence. Show the output to the user, then respond natur
609
620
 
610
621
  ## Core Files
611
622
 
623
+ Atris is the source of truth. This file is only an adapter for tools that read
624
+ \`AGENTS.md\`; do not turn it into a parallel brain. Durable policy, workflow,
625
+ task truth, proof, review, and backend/cloud sync all flow through Atris.
626
+
612
627
  | File | Purpose |
613
628
  |------|---------|
629
+ | \`atris/atris.md\` | Protocol/backbone for this workspace |
614
630
  | \`atris/PERSONA.md\` | Communication style (read first) |
615
631
  | \`atris task\` | Current tasks, claims, dialogue, proof |
616
632
  | \`.atris/state/tasks.projection.json\` | Readable task projection for UIs/agents |
617
633
  | \`atris/TODO.md\` | Rendered/legacy task view only |
618
634
  | \`atris/MAP.md\` | Navigation (where is X?) |
619
635
 
636
+ ## Agent Contract
637
+
638
+ Every agent should leave four artifacts another agent can trust:
639
+
640
+ | Artifact | Where |
641
+ |----------|-------|
642
+ | Objective | \`atris task note <id> "Goal / files / done / check"\` |
643
+ | Navigation | \`atris/MAP.md\` when a new route or file location is learned |
644
+ | Change | Small git diff in declared files only |
645
+ | Proof ready | \`atris task ready <id> --proof "<commands or receipt>"\` |
646
+ | Human accept | \`atris task accept <id>\` |
647
+
648
+ Do not rely on chat context. Put the task, file pointers, and proof on disk.
649
+ Do not write new operating doctrine here first; add it to Atris policy, skills,
650
+ wiki, or \`atris/atris.md\`, then regenerate this adapter if needed.
651
+
652
+ Native goals and task approval are separate gates:
653
+
654
+ \`\`\`text
655
+ Agent proof ready -> native goal can complete
656
+ Human accept -> task Done + AgentXP awarded
657
+ \`\`\`
658
+
659
+ Always-on agents should move proof-backed work to Review, complete their native
660
+ goal, then continue the mission loop with the next goal. They must not run
661
+ \`atris task accept\` or claim AgentXP unless a human approved the proof.
662
+
620
663
  ## Workflow
621
664
 
622
665
  \`\`\`
@@ -625,6 +668,20 @@ BUILD → atris do (execute tasks)
625
668
  CHECK → atris review (verify + cleanup)
626
669
  \`\`\`
627
670
 
671
+ ## Mission Autonomy
672
+
673
+ Use \`atris mission\` when work should survive this chat or run as an autonomous loop.
674
+
675
+ \`\`\`
676
+ member -> mission start --verify -> status --status active -> one bounded step -> mission tick --verify -> receipt -> complete|run|stop
677
+ \`\`\`
678
+
679
+ - Start current-agent work: \`atris mission start "<objective>" --owner <member> --runner codex_goal --lane code --verify "<cmd>" --stop "<condition>"\`
680
+ - Start headless Claude work: add \`--runner claude --cadence "15m" --always-on\`, then use \`atris mission run <id> --max-ticks 4 --complete-on-pass\`.
681
+ - Resume: \`atris mission status --status active --json\`, then pick the mission matching your owner/member.
682
+ - Prove: after one bounded step, run \`atris mission tick <id> --verify --summary "<what changed>"\`.
683
+ - Close: if the verifier passes, run \`atris mission complete <id> --proof "<receipt_path>"\`; if current-agent work should keep going, repeat status -> step -> tick.
684
+
628
685
  ## Rules
629
686
 
630
687
  - [ ] 3-4 sentences max per response
@@ -632,8 +689,12 @@ CHECK → atris review (verify + cleanup)
632
689
  - [ ] Check MAP.md before touching code
633
690
  - [ ] Run \`atris task list\` or \`atris task next\` before picking work
634
691
  - [ ] Claim tasks with \`atris task claim <id> --as <agent>\`
635
- - [ ] Finish tasks with proof via \`atris task finish <id> --proof "..."\`
692
+ - [ ] Move agent-completed work to Review via \`atris task ready <id> --proof "..."\`
693
+ - [ ] Complete native Codex/Claude goals after proof is in Review, so always-on work can continue
694
+ - [ ] Only use \`atris task accept <id>\` when the human has approved the proof
695
+ - [ ] Keep durable learning in Atris-owned policy/skill/wiki/task state; keep \`AGENTS.md\` as a generated/pointer layer
636
696
  - [ ] Treat \`atris/TODO.md\` as a rendered view; do not manually use it as the source of truth
697
+ - [ ] Use \`atris-labs\` for the Atris Labs business computer slug in docs and links
637
698
 
638
699
  ## Anti-patterns
639
700
 
@@ -670,6 +731,22 @@ CHECK → atris review (verify + cleanup)
670
731
  console.log('✓ Created AGENTS.md (for Codex)');
671
732
  }
672
733
 
734
+ // .devin/config.local.json for Devin for Terminal
735
+ const devinConfigDir = path.join(process.cwd(), '.devin');
736
+ const devinConfigFile = path.join(devinConfigDir, 'config.local.json');
737
+ if (!fs.existsSync(devinConfigFile)) {
738
+ fs.mkdirSync(devinConfigDir, { recursive: true });
739
+ const devinConfig = {
740
+ permissions: {
741
+ allow: [
742
+ 'Exec(atris)',
743
+ ],
744
+ },
745
+ };
746
+ fs.writeFileSync(devinConfigFile, `${JSON.stringify(devinConfig, null, 2)}\n`);
747
+ console.log('✓ Created .devin/config.local.json (for Devin)');
748
+ }
749
+
673
750
  // .claude/commands/atris.md for Claude Code
674
751
  const claudeCommandsDir = path.join(process.cwd(), '.claude', 'commands');
675
752
  const claudeCommandFile = path.join(claudeCommandsDir, 'atris.md');
@@ -680,7 +757,7 @@ description: Activate Atris context - loads TODO.md, journal, and persona
680
757
  allowed-tools: Read, Bash, Glob, Grep
681
758
  ---
682
759
 
683
- Read @AGENTS.md then run \`atris\` command.
760
+ Run \`atris\` and read \`atris/atris.md\`; @AGENTS.md is only a tool adapter.
684
761
 
685
762
  Follow the workflow: plan → do → review
686
763