atris 2.0.21 → 2.2.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,288 @@
1
+ ---
2
+ name: email-agent
3
+ description: Gmail integration via AtrisOS API. Read, send, archive emails. Use when user asks about email, inbox, or wants to send/check messages.
4
+ ---
5
+
6
+ # Email Agent
7
+
8
+ > Drop this in `~/.claude/skills/email-agent/SKILL.md` and Claude Code becomes your email assistant.
9
+
10
+ ## Bootstrap (ALWAYS Run First)
11
+
12
+ Before any email operation, run this bootstrap to ensure everything is set up:
13
+
14
+ ```bash
15
+ #!/bin/bash
16
+ set -e
17
+
18
+ # 1. Check if atris CLI is installed
19
+ if ! command -v atris &> /dev/null; then
20
+ echo "Installing atris CLI..."
21
+ npm install -g atris
22
+ fi
23
+
24
+ # 2. Check if logged in to AtrisOS
25
+ if [ ! -f ~/.atris/credentials.json ]; then
26
+ echo "Not logged in to AtrisOS."
27
+ echo ""
28
+ echo "Option 1 (interactive): Run 'atris login' and follow prompts"
29
+ echo "Option 2 (non-interactive): Get token from https://atris.ai/auth/cli"
30
+ echo " Then run: atris login --token YOUR_TOKEN"
31
+ echo ""
32
+ exit 1
33
+ fi
34
+
35
+ # 3. Extract token (try node first, then python3, then jq)
36
+ if command -v node &> /dev/null; then
37
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
38
+ elif command -v python3 &> /dev/null; then
39
+ TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
40
+ elif command -v jq &> /dev/null; then
41
+ TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
42
+ else
43
+ echo "Error: Need node, python3, or jq to read credentials"
44
+ exit 1
45
+ fi
46
+
47
+ # 4. Check Gmail connection status (also validates token)
48
+ STATUS=$(curl -s "https://api.atris.ai/api/integrations/gmail/status" \
49
+ -H "Authorization: Bearer $TOKEN")
50
+
51
+ # Check for token expiry
52
+ if echo "$STATUS" | grep -q "Token expired\|Not authenticated"; then
53
+ echo "Token expired. Please re-authenticate:"
54
+ echo " Run: atris login --force"
55
+ echo " Or get new token from: https://atris.ai/auth/cli"
56
+ exit 1
57
+ fi
58
+
59
+ # Parse connected status
60
+ if command -v node &> /dev/null; then
61
+ CONNECTED=$(node -e "console.log(JSON.parse('$STATUS').connected || false)")
62
+ elif command -v python3 &> /dev/null; then
63
+ CONNECTED=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('connected', False))")
64
+ else
65
+ CONNECTED=$(echo "$STATUS" | jq -r '.connected // false')
66
+ fi
67
+
68
+ if [ "$CONNECTED" != "true" ] && [ "$CONNECTED" != "True" ]; then
69
+ echo "Gmail not connected. Getting authorization URL..."
70
+ AUTH=$(curl -s -X POST "https://api.atris.ai/api/integrations/gmail/start" \
71
+ -H "Authorization: Bearer $TOKEN" \
72
+ -H "Content-Type: application/json" \
73
+ -d '{}')
74
+
75
+ if command -v node &> /dev/null; then
76
+ URL=$(node -e "console.log(JSON.parse('$AUTH').auth_url || '')")
77
+ elif command -v python3 &> /dev/null; then
78
+ URL=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('auth_url', ''))")
79
+ else
80
+ URL=$(echo "$AUTH" | jq -r '.auth_url // empty')
81
+ fi
82
+
83
+ echo ""
84
+ echo "Open this URL to connect your Gmail:"
85
+ echo "$URL"
86
+ echo ""
87
+ echo "After authorizing, run your email command again."
88
+ exit 0
89
+ fi
90
+
91
+ echo "Ready. Gmail is connected."
92
+ export ATRIS_TOKEN="$TOKEN"
93
+ ```
94
+
95
+ **Important**: Run this script ONCE before email operations. If it exits with instructions, follow them, then run again.
96
+
97
+ ---
98
+
99
+ ## API Reference
100
+
101
+ Base: `https://api.atris.ai/api/integrations/gmail`
102
+
103
+ All requests require: `-H "Authorization: Bearer $TOKEN"`
104
+
105
+ ### Get Token (after bootstrap)
106
+ ```bash
107
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
108
+ ```
109
+
110
+ ### List Emails
111
+ ```bash
112
+ curl -s "https://api.atris.ai/api/integrations/gmail/messages?query=in:inbox&max_results=20" \
113
+ -H "Authorization: Bearer $TOKEN"
114
+ ```
115
+
116
+ **Query syntax** (Gmail search):
117
+ - `in:inbox` — inbox only
118
+ - `in:inbox newer_than:1d` — today's emails
119
+ - `is:unread` — unread only
120
+ - `from:someone@example.com` — from specific sender
121
+ - `subject:invoice` — subject contains word
122
+ - `has:attachment` — emails with attachments
123
+
124
+ ### Read Single Email
125
+ ```bash
126
+ curl -s "https://api.atris.ai/api/integrations/gmail/messages/{message_id}" \
127
+ -H "Authorization: Bearer $TOKEN"
128
+ ```
129
+
130
+ ### Send Email
131
+ ```bash
132
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/send" \
133
+ -H "Authorization: Bearer $TOKEN" \
134
+ -H "Content-Type: application/json" \
135
+ -d '{
136
+ "to": "recipient@example.com",
137
+ "subject": "Subject line",
138
+ "body": "Email body text"
139
+ }'
140
+ ```
141
+
142
+ **With CC/BCC:**
143
+ ```bash
144
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/send" \
145
+ -H "Authorization: Bearer $TOKEN" \
146
+ -H "Content-Type: application/json" \
147
+ -d '{
148
+ "to": "recipient@example.com",
149
+ "cc": "copy@example.com",
150
+ "bcc": ["hidden1@example.com", "hidden2@example.com"],
151
+ "subject": "Subject line",
152
+ "body": "Email body text"
153
+ }'
154
+ ```
155
+
156
+ **With attachments:**
157
+ ```bash
158
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/send" \
159
+ -H "Authorization: Bearer $TOKEN" \
160
+ -H "Content-Type: application/json" \
161
+ -d '{
162
+ "to": "recipient@example.com",
163
+ "subject": "With attachment",
164
+ "body": "See attached.",
165
+ "attachments": [{"filename": "report.txt", "content": "base64-encoded-content", "mime_type": "text/plain"}]
166
+ }'
167
+ ```
168
+
169
+ ### Archive Email
170
+ ```bash
171
+ # Single message
172
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/archive" \
173
+ -H "Authorization: Bearer $TOKEN"
174
+
175
+ # Batch archive
176
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/batch-archive" \
177
+ -H "Authorization: Bearer $TOKEN" \
178
+ -H "Content-Type: application/json" \
179
+ -d '{"message_ids": ["id1", "id2", "id3"]}'
180
+ ```
181
+
182
+ ### Check Status
183
+ ```bash
184
+ curl -s "https://api.atris.ai/api/integrations/gmail/status" \
185
+ -H "Authorization: Bearer $TOKEN"
186
+ ```
187
+
188
+ ### Disconnect Gmail
189
+ ```bash
190
+ curl -s -X DELETE "https://api.atris.ai/api/integrations/gmail" \
191
+ -H "Authorization: Bearer $TOKEN"
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Workflows
197
+
198
+ ### "Check my emails"
199
+ 1. Run bootstrap
200
+ 2. List messages: `GET /messages?query=in:inbox%20newer_than:1d&max_results=20`
201
+ 3. Display: sender, subject, snippet for each
202
+
203
+ ### "Send email to X about Y"
204
+ 1. Run bootstrap
205
+ 2. Draft email content
206
+ 3. **Show user the draft for approval**
207
+ 4. On approval: `POST /send` with `{to, subject, body}`
208
+ 5. Confirm: "Email sent!"
209
+
210
+ ### "Clean up my inbox"
211
+ 1. Run bootstrap
212
+ 2. List: `GET /messages?query=in:inbox&max_results=50`
213
+ 3. Identify archivable emails (see rules below)
214
+ 4. **Show user what will be archived, get approval**
215
+ 5. Batch archive: `POST /batch-archive`
216
+
217
+ ### "Archive all from [sender]"
218
+ 1. Run bootstrap
219
+ 2. Search: `GET /messages?query=from:{sender}`
220
+ 3. Collect message IDs
221
+ 4. **Confirm with user**: "Found N emails from {sender}. Archive all?"
222
+ 5. Batch archive
223
+
224
+ ---
225
+
226
+ ## Auto-Archive Rules
227
+
228
+ **Safe to suggest archiving:**
229
+ - From: `noreply@`, `notifications@`, `newsletter@`, `no-reply@`
230
+ - Subject contains: digest, newsletter, notification, weekly update, daily summary
231
+ - Marketing: promotional, unsubscribe link present
232
+
233
+ **NEVER auto-archive (always keep):**
234
+ - Subject contains: invoice, receipt, payment, urgent, action required, password, verification, security
235
+ - From known contacts (check if user has replied to them)
236
+ - Flagged/starred messages
237
+
238
+ **Always ask before archiving.** Never archive without explicit user approval.
239
+
240
+ ---
241
+
242
+ ## Error Handling
243
+
244
+ | Error | Meaning | Solution |
245
+ |-------|---------|----------|
246
+ | `Token expired` | AtrisOS session expired | Run `atris login` |
247
+ | `Gmail not connected` | OAuth not completed | Re-run bootstrap, complete OAuth flow |
248
+ | `401 Unauthorized` | Invalid/expired token | Run `atris login` |
249
+ | `400 Gmail not connected` | No Gmail credentials | Complete OAuth via bootstrap |
250
+ | `429 Rate limited` | Too many requests | Wait 60s, retry |
251
+ | `Invalid grant` | Google revoked access | Re-connect Gmail via bootstrap |
252
+
253
+ ---
254
+
255
+ ## Security Model
256
+
257
+ 1. **Local token** (`~/.atris/credentials.json`): Your AtrisOS auth token, stored locally with 600 permissions. Same model as AWS CLI, GitHub CLI.
258
+
259
+ 2. **Gmail credentials**: Your Gmail refresh token is stored **server-side** in AtrisOS encrypted vault. Never stored on your local machine.
260
+
261
+ 3. **Access control**: AtrisOS API enforces that you can only access your own email. No cross-user access possible.
262
+
263
+ 4. **OAuth scopes**: Only requests necessary Gmail permissions (read, send, modify labels).
264
+
265
+ 5. **HTTPS only**: All API communication encrypted in transit.
266
+
267
+ ---
268
+
269
+ ## Quick Reference
270
+
271
+ ```bash
272
+ # Setup (one time)
273
+ npm install -g atris && atris login
274
+
275
+ # Get token
276
+ TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
277
+
278
+ # Check connection
279
+ curl -s "https://api.atris.ai/api/integrations/gmail/status" -H "Authorization: Bearer $TOKEN"
280
+
281
+ # List inbox
282
+ curl -s "https://api.atris.ai/api/integrations/gmail/messages?query=in:inbox&max_results=10" -H "Authorization: Bearer $TOKEN"
283
+
284
+ # Send email
285
+ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/send" \
286
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
287
+ -d '{"to":"email@example.com","subject":"Hi","body":"Hello!"}'
288
+ ```
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: memory
3
+ description: Search and reason over Atris journal history. Use when user asks about past work, decisions, history, or patterns. Uses RLM pattern (grep first, reason second).
4
+ ---
5
+
1
6
  # Atris Memory Skill
2
7
 
3
8
  Search and reason over Atris journal history using the RLM pattern (grep first, reason second).
@@ -85,6 +85,32 @@ Feature complete. Ready for review? (y/n)
85
85
  4. **Run tests after changes** — Catch issues immediately
86
86
  5. **No shortcuts** — Follow the build.md steps exactly
87
87
  6. **Anti-slop aware** — Read `atris/policies/ANTISLOP.md` before writing. No sparkles, no filler, no purple prose.
88
+ 7. **Stay in scope** — Only touch files listed in the task. If you need to change something outside scope, stop and flag it. That's a new task.
89
+ 8. **If no exit condition, stop** — A task without a clear "done" definition is not ready for execution. Send it back to navigator.
90
+
91
+ ---
92
+
93
+ ## After Each Task
94
+
95
+ Report what you learned in 1-2 sentences. What did you discover about the codebase? What was surprising? This compounds context for the next task.
96
+
97
+ ```
98
+ Done: [what was completed]
99
+ Learned: [what you now know that you didn't before]
100
+ ```
101
+
102
+ ## Update validate.md
103
+
104
+ After building, update the feature's `validate.md`:
105
+
106
+ - **Context section** — Add what you learned about the codebase during execution. File locations, patterns, gotchas. This is portable knowledge for the next agent.
107
+ - **Errors Hit section** — If you hit errors, document what went wrong and why. This prevents the next agent from falling in the same hole.
108
+
109
+ Don't touch the Status or Checks sections. That's the validator's job.
110
+
111
+ ## Two-Error Rule
112
+
113
+ If you hit two errors on the same task, **stop**. Don't debug from polluted context. Report what you know, update validate.md with the errors, and flag for re-scope. A fresh session with clean context and your notes will solve it faster than a tenth retry.
88
114
 
89
115
  ---
90
116
 
@@ -21,16 +21,32 @@
21
21
 
22
22
  When the human gives you an idea (messy, conversational, exploratory):
23
23
 
24
- 1. **Extract intent** — What are they trying to build? Why?
25
- 2. **Generate atris visualization** — Show them exactly what will happen (frontend boxes / backend flow / database tables)
26
- 3. **Confirm** — "Is THIS what you meant?" (y/n)
27
- 4. **Create idea.md** — Save their messy intent to `atris/features/[name]/idea.md`
28
- 5. **Generate build.md** — Create technical spec in `atris/features/[name]/build.md`
24
+ 1. **Scout first** — Read the relevant files in the codebase. Understand what exists before you plan what's next. Report what you found in 2-3 sentences.
25
+ 2. **Extract intent** — What are they trying to build? Why?
26
+ 3. **Generate atris visualization** — Show them exactly what will happen (frontend boxes / backend flow / database tables)
27
+ 4. **Confirm** — "Is THIS what you meant?" (y/n)
28
+ 5. **Create idea.md** — Save their messy intent to `atris/features/[name]/idea.md`
29
+ 6. **Generate build.md** — Create technical spec in `atris/features/[name]/build.md`
29
30
 
30
31
  **DO NOT execute.** You plan. Executor builds.
31
32
 
32
33
  ---
33
34
 
35
+ ## Task Scoping
36
+
37
+ Every task you create must be:
38
+
39
+ - **One job.** Single file scope or single function scope. If it touches 4+ files, break it into multiple tasks.
40
+ - **Clear exit condition.** State what "done" looks like in one sentence.
41
+ - **Tagged.** Mark each task `[explore]` or `[execute]`:
42
+ - `[explore]` — Read code, research, understand. Output is knowledge.
43
+ - `[execute]` — Build, change, create. Output is code or artifact.
44
+ - **Sequenced.** Put `[explore]` tasks first. They inform the `[execute]` tasks that follow.
45
+
46
+ If you can't write a clear exit condition, the task is too vague. Break it down further or start with an `[explore]` task to clarify.
47
+
48
+ ---
49
+
34
50
  ## atris Visualization Patterns
35
51
 
36
52
  Use these for 99% of dev work:
@@ -102,6 +118,27 @@ tests:
102
118
  - test scenario 2
103
119
  ```
104
120
 
121
+ **validate.md:**
122
+ ```markdown
123
+ # Feature Name — Validation
124
+
125
+ ## Status
126
+ v0 — planned YYYY-MM-DD
127
+ Exit condition: [what "done" looks like in one sentence]
128
+
129
+ ## Checks
130
+ - [verifiable step: run X, expect Y]
131
+ - [verifiable step: check Z]
132
+
133
+ ## Context
134
+ [empty until executor fills in learnings]
135
+
136
+ ## Errors Hit
137
+ [empty until executor reports failures]
138
+ ```
139
+
140
+ Navigator creates validate.md with Status (v0 — planned) and Checks. The executor fills in Context and Errors as it builds. The validator updates Status to v1 — shipped when it passes.
141
+
105
142
  ---
106
143
 
107
144
  ## Rules
@@ -84,17 +84,43 @@ Before approving, think 3 times:
84
84
  - All steps completed?
85
85
  - Nothing skipped?
86
86
 
87
- **Think 2: Edge Cases**
87
+ **Think 2: Scope Check**
88
+ - Did the executor stay in scope? Only files listed in the task should be touched.
89
+ - Was the task actually one job? If it sprawled into multiple concerns, flag it.
90
+ - Did the exit condition get met? Not "close enough" — exactly met.
91
+
92
+ **Think 3: Edge Cases**
88
93
  - What could break?
89
94
  - Error handling present?
90
95
  - Boundary conditions covered?
91
96
 
92
- **Think 3: Integration**
97
+ **Think 4: Integration**
93
98
  - Does it work with existing code?
94
99
  - Breaking changes?
95
100
  - Dependencies still valid?
96
101
 
97
- **Then decide:** Approve or block.
102
+ **Then decide:** Approve or block. If scope crept, block and split into proper tasks.
103
+
104
+ ## Update validate.md
105
+
106
+ When a feature passes validation:
107
+
108
+ 1. **Update Status** — Change from `v0 — planned` to `v1 — shipped YYYY-MM-DD` with the exit condition that was met.
109
+ 2. **Verify Checks** — Run every check in the Checks section. All must pass.
110
+ 3. **Review Context** — Make sure the executor's learnings are useful for future agents.
111
+ 4. **Review Errors** — If errors were hit, confirm the root cause is documented.
112
+
113
+ When iterating on a shipped feature, append the new version:
114
+ ```
115
+ ## Status
116
+ v2 — shipped 2026-02-15
117
+ Exit condition: Rate limiting active, 429 after 100 req/min.
118
+
119
+ v1 — shipped 2026-02-07
120
+ Exit condition: Unauthenticated requests return 401, test passes.
121
+ ```
122
+
123
+ Status is the scoreboard. One line per version. Anyone can look at validate.md and know exactly what state the feature is in.
98
124
 
99
125
  ---
100
126
 
package/atris.md CHANGED
@@ -11,7 +11,7 @@
11
11
  1. Load context (ONE time, remember for session):
12
12
  - `atris/logs/YYYY/YYYY-MM-DD.md` (today's journal)
13
13
  - `atris/MAP.md` (navigation overview)
14
- - `atris/agent_team/*.md` (all agent specs)
14
+ - `atris/team/*.md` (all agent specs)
15
15
 
16
16
  2. Output this EXACT box:
17
17
 
@@ -88,15 +88,34 @@ Stage: PLAN → do → review (capitalize current stage)
88
88
  ## WORKFLOW
89
89
 
90
90
  ```
91
- plan → do → review
91
+ scout → plan → do → review
92
92
  ```
93
93
 
94
+ - **SCOUT** — Read relevant files first. Understand before you act. Report what you found.
94
95
  - **PLAN** — ASCII visualization, get approval, NO code yet
95
96
  - **DO** — Execute step-by-step, update journal
96
97
  - **REVIEW** — Test, validate, clean up, delete completed tasks
97
98
 
98
99
  ---
99
100
 
101
+ ## TASK RULES
102
+
103
+ Every task must follow these rules. No exceptions.
104
+
105
+ **One job per task.** If a task touches more than 2-3 files, break it down. If you can't describe "done" in one sentence, it's too big.
106
+
107
+ **Clear exit condition.** Every task states what "done" looks like. Not "improve auth" — instead: "Add session check to upload handler. Done when: unauthenticated requests return 401 and test passes."
108
+
109
+ **Tag every task:**
110
+ - `[explore]` — Ambiguous. Needs reading, research, judgment. Output is understanding.
111
+ - `[execute]` — Precise. Route is clear. Just do it. Output is code or artifact.
112
+
113
+ **Explore before execute.** When starting a new area of work, the first tasks should be `[explore]`. Read the files. Map the space. Report what you found. Then plan `[execute]` tasks based on what you learned.
114
+
115
+ **Sequence matters.** Order tasks so each one builds context for the next. Early tasks should teach you about the problem. Later tasks use that knowledge.
116
+
117
+ ---
118
+
100
119
  ## AGENTS
101
120
 
102
121
  | Command | Agent | Guardrail |
@@ -108,7 +127,7 @@ plan → do → review
108
127
 
109
128
  `atris next` = auto-selects agent based on journal state
110
129
 
111
- Specs loaded at activate from `agent_team/*.md`
130
+ Specs loaded at activate from `team/*.md`
112
131
 
113
132
  ---
114
133
 
@@ -143,7 +162,7 @@ Specs loaded at activate from `agent_team/*.md`
143
162
  | `TODO.md` | Task queue (target: 0) |
144
163
  | `logs/YYYY/MM-DD.md` | Journal (daily) |
145
164
  | `PERSONA.md` | Communication style |
146
- | `agent_team/` | Agent behaviors |
165
+ | `team/` | Agent behaviors |
147
166
  | `atrisDev.md` | Full spec (reference) |
148
167
 
149
168
  ---