atris 2.2.0 → 2.2.2
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/GETTING_STARTED.md +2 -2
- package/README.md +2 -2
- package/atris/GETTING_STARTED.md +2 -2
- package/atris/atris.md +4 -3
- package/atris/features/README.md +41 -15
- package/atris/skills/README.md +28 -2
- package/atris/skills/atris/SKILL.md +7 -0
- package/atris/skills/autopilot/SKILL.md +8 -4
- package/atris/skills/backend/SKILL.md +6 -1
- package/atris/skills/calendar/SKILL.md +301 -0
- package/atris/skills/clawhub/atris/SKILL.md +121 -0
- package/atris/skills/copy-editor/SKILL.md +7 -8
- package/atris/skills/design/SKILL.md +5 -1
- package/atris/skills/drive/SKILL.md +363 -0
- package/atris/skills/email-agent/SKILL.md +88 -0
- package/atris/skills/memory/SKILL.md +3 -0
- package/atris/skills/meta/SKILL.md +4 -0
- package/atris/skills/skill-improver/SKILL.md +147 -0
- package/atris/skills/slack/SKILL.md +320 -0
- package/atris/skills/writing/SKILL.md +3 -0
- package/atris/team/brainstormer.md +1 -0
- package/atris/team/executor.md +1 -0
- package/atris/team/launcher.md +1 -0
- package/atris/team/navigator.md +2 -0
- package/atris/team/validator.md +15 -0
- package/atris.md +17 -0
- package/bin/atris.js +14 -2
- package/commands/init.js +13 -0
- package/commands/skill.js +496 -0
- package/commands/status.js +9 -1
- package/commands/workflow.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill-improver
|
|
3
|
+
description: Audit and improve Claude skills against the Anthropic skill guide. Use when creating new skills, improving existing ones, or preparing skills for ClawHub distribution. Triggers on skill audit, improve skill, new skill, skill quality, or ClawHub publish.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tags:
|
|
6
|
+
- developer-tools
|
|
7
|
+
- skill-management
|
|
8
|
+
- quality
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Skill Improver
|
|
12
|
+
|
|
13
|
+
Audit and improve skills to match the Anthropic skill guide standard.
|
|
14
|
+
|
|
15
|
+
## When to activate
|
|
16
|
+
|
|
17
|
+
- User wants to create a new skill
|
|
18
|
+
- User wants to improve an existing skill
|
|
19
|
+
- Preparing a skill for ClawHub or external distribution
|
|
20
|
+
- After `atris skill audit` reports warnings or failures
|
|
21
|
+
|
|
22
|
+
## The standard
|
|
23
|
+
|
|
24
|
+
A well-formed skill has:
|
|
25
|
+
|
|
26
|
+
1. YAML frontmatter with `name` (kebab-case, matches folder), `description` (WHAT + WHEN + triggers, under 1024 chars), `version` (semver), `tags`
|
|
27
|
+
2. No XML tags anywhere in the file
|
|
28
|
+
3. Clear numbered instructions with concrete steps
|
|
29
|
+
4. Error handling guidance
|
|
30
|
+
5. Examples of input and expected output
|
|
31
|
+
6. Under 5000 words in SKILL.md (move detail to `references/` subdirectory)
|
|
32
|
+
|
|
33
|
+
## Audit process
|
|
34
|
+
|
|
35
|
+
1. Run `atris skill audit [name]` for mechanical checks (12 automated checks)
|
|
36
|
+
2. Read the SKILL.md for qualitative issues:
|
|
37
|
+
- Is the description specific enough to trigger correctly?
|
|
38
|
+
- Do instructions have concrete steps, not vague guidance?
|
|
39
|
+
- Are there before/after examples?
|
|
40
|
+
- Is error handling covered?
|
|
41
|
+
- Would a new agent understand this without extra context?
|
|
42
|
+
3. Score: mechanical (CLI) + qualitative (your judgment)
|
|
43
|
+
|
|
44
|
+
## Fixing common problems
|
|
45
|
+
|
|
46
|
+
### Weak descriptions
|
|
47
|
+
|
|
48
|
+
Bad: "Essay writing skill. Triggers on: essay, draft"
|
|
49
|
+
|
|
50
|
+
Good: "Structured essay writing with approval gates at each stage (inbox, outline, panel, write, passes). Use when writing essays, drafts, outlines, or long-form content. Triggers on essay, draft, write, outline, or long-form."
|
|
51
|
+
|
|
52
|
+
Pattern: WHAT it does (1 sentence) + WHEN to use it (1 sentence) + trigger words woven in.
|
|
53
|
+
|
|
54
|
+
### Missing trigger phrases
|
|
55
|
+
|
|
56
|
+
Triggers go IN the description field, not as a separate `triggers` key. The Anthropic spec only recognizes `name` and `description` as required fields.
|
|
57
|
+
|
|
58
|
+
### Vague instructions
|
|
59
|
+
|
|
60
|
+
Bad: "Follow the writing process"
|
|
61
|
+
|
|
62
|
+
Good:
|
|
63
|
+
1. Capture raw ideas in inbox format
|
|
64
|
+
2. Build topic skeleton with evidence slots
|
|
65
|
+
3. Run panel review (AI challenges claims, user approves)
|
|
66
|
+
4. Write section by section, getting approval at each gate
|
|
67
|
+
5. Run three passes: argument (AI), read-aloud (human), sanity (both)
|
|
68
|
+
|
|
69
|
+
### Name mismatch
|
|
70
|
+
|
|
71
|
+
The `name` field must match the folder name exactly. Folder `backend` needs `name: backend`, not `name: atris-backend`.
|
|
72
|
+
|
|
73
|
+
### XML tags in content
|
|
74
|
+
|
|
75
|
+
XML-style tags (angle brackets around words) are forbidden. Replace them with bracket notation like `[text]` or plain text. The skill system rejects XML in SKILL.md content.
|
|
76
|
+
|
|
77
|
+
## Creating a new skill
|
|
78
|
+
|
|
79
|
+
1. Create folder: `atris/skills/[kebab-name]/`
|
|
80
|
+
2. Create `SKILL.md` with this template:
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
---
|
|
84
|
+
name: your-skill-name
|
|
85
|
+
description: What this skill does. Use when [specific scenarios]. Triggers on [keywords].
|
|
86
|
+
version: 1.0.0
|
|
87
|
+
tags:
|
|
88
|
+
- tag-one
|
|
89
|
+
- tag-two
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
# Your Skill Name
|
|
93
|
+
|
|
94
|
+
One-line summary of what this skill does.
|
|
95
|
+
|
|
96
|
+
## When to activate
|
|
97
|
+
|
|
98
|
+
- Scenario 1
|
|
99
|
+
- Scenario 2
|
|
100
|
+
|
|
101
|
+
## Instructions
|
|
102
|
+
|
|
103
|
+
### Step 1: [First action]
|
|
104
|
+
|
|
105
|
+
Concrete explanation with example.
|
|
106
|
+
|
|
107
|
+
### Step 2: [Second action]
|
|
108
|
+
|
|
109
|
+
Concrete explanation with example.
|
|
110
|
+
|
|
111
|
+
## Examples
|
|
112
|
+
|
|
113
|
+
### Example 1: [Common scenario]
|
|
114
|
+
|
|
115
|
+
User says: "..."
|
|
116
|
+
Actions: ...
|
|
117
|
+
Result: ...
|
|
118
|
+
|
|
119
|
+
## Troubleshooting
|
|
120
|
+
|
|
121
|
+
### Error: [Common problem]
|
|
122
|
+
Cause: [Why]
|
|
123
|
+
Fix: [How]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
3. Run `atris skill audit [name]` to validate
|
|
127
|
+
4. Run `atris update` to symlink to `.claude/skills/`
|
|
128
|
+
|
|
129
|
+
## Quality tiers
|
|
130
|
+
|
|
131
|
+
- **Bronze**: Passes all 12 mechanical checks from `atris skill audit`
|
|
132
|
+
- **Silver**: Bronze + good description + numbered steps + examples
|
|
133
|
+
- **Gold**: Silver + error handling + progressive disclosure + tested in production
|
|
134
|
+
|
|
135
|
+
Gold standard reference: `atris/skills/clawhub/atris/SKILL.md`
|
|
136
|
+
|
|
137
|
+
## Distribution checklist
|
|
138
|
+
|
|
139
|
+
Before publishing to ClawHub or sharing externally:
|
|
140
|
+
|
|
141
|
+
1. All 12 audit checks pass (`atris skill audit [name]`)
|
|
142
|
+
2. Description under 1024 chars, includes WHAT + WHEN + triggers
|
|
143
|
+
3. Version field set (semver)
|
|
144
|
+
4. Tags present (3-5 relevant tags)
|
|
145
|
+
5. No internal references (paths must be relative, no hardcoded project paths)
|
|
146
|
+
6. No README.md inside the skill folder
|
|
147
|
+
7. SKILL.md is self-contained or uses `references/` for supplementary docs
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slack
|
|
3
|
+
description: Slack integration via AtrisOS API. Read messages, send as yourself, search conversations, manage DMs. Use when user asks about Slack, messages, channels, or team communication.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tags:
|
|
6
|
+
- slack
|
|
7
|
+
- backend
|
|
8
|
+
- messaging
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Slack Agent
|
|
12
|
+
|
|
13
|
+
> Drop this in `~/.claude/skills/slack/SKILL.md` and Claude Code becomes your Slack assistant.
|
|
14
|
+
|
|
15
|
+
## Bootstrap (ALWAYS Run First)
|
|
16
|
+
|
|
17
|
+
Before any Slack operation, run this bootstrap to ensure everything is set up:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
#!/bin/bash
|
|
21
|
+
set -e
|
|
22
|
+
|
|
23
|
+
# 1. Check if atris CLI is installed
|
|
24
|
+
if ! command -v atris &> /dev/null; then
|
|
25
|
+
echo "Installing atris CLI..."
|
|
26
|
+
npm install -g atris
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# 2. Check if logged in to AtrisOS
|
|
30
|
+
if [ ! -f ~/.atris/credentials.json ]; then
|
|
31
|
+
echo "Not logged in to AtrisOS."
|
|
32
|
+
echo ""
|
|
33
|
+
echo "Option 1 (interactive): Run 'atris login' and follow prompts"
|
|
34
|
+
echo "Option 2 (non-interactive): Get token from https://atris.ai/auth/cli"
|
|
35
|
+
echo " Then run: atris login --token YOUR_TOKEN"
|
|
36
|
+
echo ""
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# 3. Extract token
|
|
41
|
+
if command -v node &> /dev/null; then
|
|
42
|
+
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
43
|
+
elif command -v python3 &> /dev/null; then
|
|
44
|
+
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
|
|
45
|
+
elif command -v jq &> /dev/null; then
|
|
46
|
+
TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
|
|
47
|
+
else
|
|
48
|
+
echo "Error: Need node, python3, or jq to read credentials"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# 4. Check Slack connection status
|
|
53
|
+
STATUS=$(curl -s "https://api.atris.ai/api/integrations/slack/status" \
|
|
54
|
+
-H "Authorization: Bearer $TOKEN")
|
|
55
|
+
|
|
56
|
+
if echo "$STATUS" | grep -q "Token expired\|Not authenticated"; then
|
|
57
|
+
echo "Token expired. Please re-authenticate:"
|
|
58
|
+
echo " Run: atris login --force"
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if command -v node &> /dev/null; then
|
|
63
|
+
CONNECTED=$(node -e "try{console.log(JSON.parse('$STATUS').connected||false)}catch(e){console.log(false)}")
|
|
64
|
+
elif command -v python3 &> /dev/null; then
|
|
65
|
+
CONNECTED=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('connected', False))")
|
|
66
|
+
else
|
|
67
|
+
CONNECTED=$(echo "$STATUS" | jq -r '.connected // false')
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ "$CONNECTED" != "true" ] && [ "$CONNECTED" != "True" ]; then
|
|
71
|
+
echo "Slack not connected. Getting authorization URL..."
|
|
72
|
+
AUTH=$(curl -s -X POST "https://api.atris.ai/api/integrations/slack/start" \
|
|
73
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
74
|
+
-H "Content-Type: application/json" \
|
|
75
|
+
-d '{"mode":"personal"}')
|
|
76
|
+
|
|
77
|
+
if command -v node &> /dev/null; then
|
|
78
|
+
URL=$(node -e "try{console.log(JSON.parse('$AUTH').auth_url||'')}catch(e){console.log('')}")
|
|
79
|
+
elif command -v python3 &> /dev/null; then
|
|
80
|
+
URL=$(echo "$AUTH" | python3 -c "import sys,json; print(json.load(sys.stdin).get('auth_url', ''))")
|
|
81
|
+
else
|
|
82
|
+
URL=$(echo "$AUTH" | jq -r '.auth_url // empty')
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
echo ""
|
|
86
|
+
echo "Open this URL to connect your Slack:"
|
|
87
|
+
echo "$URL"
|
|
88
|
+
echo ""
|
|
89
|
+
echo "After authorizing, run your command again."
|
|
90
|
+
exit 0
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
echo "Ready. Slack is connected."
|
|
94
|
+
export ATRIS_TOKEN="$TOKEN"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## API Reference
|
|
100
|
+
|
|
101
|
+
Base: `https://api.atris.ai/api/integrations`
|
|
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
|
+
---
|
|
111
|
+
|
|
112
|
+
## Personal Endpoints (send/read as yourself)
|
|
113
|
+
|
|
114
|
+
These use your personal Slack token. Messages appear as YOU, not a bot.
|
|
115
|
+
|
|
116
|
+
### List Your Channels & DMs
|
|
117
|
+
```bash
|
|
118
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/channels" \
|
|
119
|
+
-H "Authorization: Bearer $TOKEN"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### List Your DMs
|
|
123
|
+
```bash
|
|
124
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/dms" \
|
|
125
|
+
-H "Authorization: Bearer $TOKEN"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Read Messages from a Channel or DM
|
|
129
|
+
```bash
|
|
130
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/messages/{channel_id}?limit=20" \
|
|
131
|
+
-H "Authorization: Bearer $TOKEN"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Send Message as Yourself
|
|
135
|
+
```bash
|
|
136
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/me/send" \
|
|
137
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
138
|
+
-H "Content-Type: application/json" \
|
|
139
|
+
-d '{
|
|
140
|
+
"channel": "C0123CHANNEL",
|
|
141
|
+
"text": "Hey team, here is the update..."
|
|
142
|
+
}'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Reply in a thread:**
|
|
146
|
+
```bash
|
|
147
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/me/send" \
|
|
148
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
149
|
+
-H "Content-Type: application/json" \
|
|
150
|
+
-d '{
|
|
151
|
+
"channel": "C0123CHANNEL",
|
|
152
|
+
"text": "Following up on this...",
|
|
153
|
+
"thread_ts": "1234567890.123456"
|
|
154
|
+
}'
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### DM Someone as Yourself
|
|
158
|
+
```bash
|
|
159
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/me/dm" \
|
|
160
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
161
|
+
-H "Content-Type: application/json" \
|
|
162
|
+
-d '{
|
|
163
|
+
"slack_user_id": "U0123USER",
|
|
164
|
+
"text": "Hey, quick question about the project..."
|
|
165
|
+
}'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Search Messages
|
|
169
|
+
```bash
|
|
170
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/search?q=quarterly+report&count=20" \
|
|
171
|
+
-H "Authorization: Bearer $TOKEN"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Workspace Endpoints
|
|
177
|
+
|
|
178
|
+
### List Channels (bot view)
|
|
179
|
+
```bash
|
|
180
|
+
curl -s "https://api.atris.ai/api/integrations/slack/channels" \
|
|
181
|
+
-H "Authorization: Bearer $TOKEN"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### List Users
|
|
185
|
+
```bash
|
|
186
|
+
curl -s "https://api.atris.ai/api/integrations/slack/users" \
|
|
187
|
+
-H "Authorization: Bearer $TOKEN"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Send as Bot
|
|
191
|
+
```bash
|
|
192
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/test-send" \
|
|
193
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
194
|
+
-H "Content-Type: application/json" \
|
|
195
|
+
-d '{
|
|
196
|
+
"channel": "C0123CHANNEL",
|
|
197
|
+
"message": "Hello from Atris!"
|
|
198
|
+
}'
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Check Connection Status
|
|
202
|
+
```bash
|
|
203
|
+
curl -s "https://api.atris.ai/api/integrations/slack/status" \
|
|
204
|
+
-H "Authorization: Bearer $TOKEN"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Disconnect Slack
|
|
208
|
+
```bash
|
|
209
|
+
curl -s -X DELETE "https://api.atris.ai/api/integrations/slack" \
|
|
210
|
+
-H "Authorization: Bearer $TOKEN"
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Workflows
|
|
216
|
+
|
|
217
|
+
### "Check my Slack messages"
|
|
218
|
+
1. Run bootstrap
|
|
219
|
+
2. List DMs: `GET /slack/me/dms`
|
|
220
|
+
3. For each open DM, read recent messages: `GET /slack/me/messages/{channel_id}?limit=5`
|
|
221
|
+
4. Resolve user names: `GET /slack/users`
|
|
222
|
+
5. Display: who messaged, what they said, when
|
|
223
|
+
|
|
224
|
+
### "Send a message to someone"
|
|
225
|
+
1. Run bootstrap
|
|
226
|
+
2. Find the user: `GET /slack/users` (search by name/email)
|
|
227
|
+
3. **Show user the draft for approval**
|
|
228
|
+
4. Send DM: `POST /slack/me/dm` with `{user_id, text}`
|
|
229
|
+
5. Confirm: "Message sent!"
|
|
230
|
+
|
|
231
|
+
### "Reply in a channel"
|
|
232
|
+
1. Run bootstrap
|
|
233
|
+
2. List channels: `GET /slack/me/channels`
|
|
234
|
+
3. Find the right channel
|
|
235
|
+
4. Read recent messages: `GET /slack/me/messages/{channel_id}`
|
|
236
|
+
5. **Show user the draft for approval**
|
|
237
|
+
6. Send: `POST /slack/me/send` with `{channel, text}`
|
|
238
|
+
|
|
239
|
+
### "Find a conversation about X"
|
|
240
|
+
1. Run bootstrap
|
|
241
|
+
2. Search: `GET /slack/me/search?q=X`
|
|
242
|
+
3. Display matching messages with channel, sender, permalink
|
|
243
|
+
|
|
244
|
+
### "What did [person] say to me?"
|
|
245
|
+
1. Run bootstrap
|
|
246
|
+
2. List users: `GET /slack/users` (find user ID)
|
|
247
|
+
3. List DMs: `GET /slack/me/dms` (find DM channel with that user)
|
|
248
|
+
4. Read messages: `GET /slack/me/messages/{channel_id}`
|
|
249
|
+
5. Display conversation
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Important Notes
|
|
254
|
+
|
|
255
|
+
- **Personal endpoints** (`/slack/me/*`) send messages as YOU, not a bot
|
|
256
|
+
- **Bot endpoints** (`/slack/channels`, `/slack/test-send`) use the bot token
|
|
257
|
+
- **Always get approval** before sending messages on behalf of the user
|
|
258
|
+
- **Thread replies**: include `thread_ts` to reply in a thread instead of creating a new message
|
|
259
|
+
- **User IDs**: Slack uses IDs like `U0123ABC`. Get them from `/slack/users` endpoint
|
|
260
|
+
- **Channel IDs**: Use IDs like `C0123ABC`. Get them from `/slack/me/channels`
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Error Handling
|
|
265
|
+
|
|
266
|
+
| Error | Meaning | Solution |
|
|
267
|
+
|-------|---------|----------|
|
|
268
|
+
| `Token expired` | AtrisOS session expired | Run `atris login` |
|
|
269
|
+
| `Slack not connected` | OAuth not completed | Re-run bootstrap |
|
|
270
|
+
| `Personal Slack not connected` | No user token | Re-connect Slack (needs re-auth for personal access) |
|
|
271
|
+
| `401 Unauthorized` | Invalid/expired token | Run `atris login` |
|
|
272
|
+
| `channel_not_found` | Invalid channel ID | Use `/slack/me/channels` to find correct ID |
|
|
273
|
+
| `not_in_channel` | User not in channel | Join the channel first |
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Security Model
|
|
278
|
+
|
|
279
|
+
1. **Local token** (`~/.atris/credentials.json`): Your AtrisOS auth token, stored locally.
|
|
280
|
+
2. **Slack credentials**: Bot token and user token stored **server-side** in AtrisOS encrypted vault.
|
|
281
|
+
3. **Two token types**: Bot token (xoxb-) for workspace operations, User token (xoxp-) for personal operations.
|
|
282
|
+
4. **Access control**: AtrisOS API enforces that you can only access your own Slack.
|
|
283
|
+
5. **HTTPS only**: All API communication encrypted in transit.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Quick Reference
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# Setup (one time)
|
|
291
|
+
npm install -g atris && atris login
|
|
292
|
+
|
|
293
|
+
# Get token
|
|
294
|
+
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
295
|
+
|
|
296
|
+
# Check connection
|
|
297
|
+
curl -s "https://api.atris.ai/api/integrations/slack/status" -H "Authorization: Bearer $TOKEN"
|
|
298
|
+
|
|
299
|
+
# List your DMs
|
|
300
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/dms" -H "Authorization: Bearer $TOKEN"
|
|
301
|
+
|
|
302
|
+
# Read messages
|
|
303
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/messages/CHANNEL_ID" -H "Authorization: Bearer $TOKEN"
|
|
304
|
+
|
|
305
|
+
# Send as yourself
|
|
306
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/me/send" \
|
|
307
|
+
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
308
|
+
-d '{"channel":"C0123","text":"Hello!"}'
|
|
309
|
+
|
|
310
|
+
# DM someone as yourself
|
|
311
|
+
curl -s -X POST "https://api.atris.ai/api/integrations/slack/me/dm" \
|
|
312
|
+
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
313
|
+
-d '{"user_id":"U0123","text":"Hey!"}'
|
|
314
|
+
|
|
315
|
+
# Search messages
|
|
316
|
+
curl -s "https://api.atris.ai/api/integrations/slack/me/search?q=project+update" -H "Authorization: Bearer $TOKEN"
|
|
317
|
+
|
|
318
|
+
# List workspace users
|
|
319
|
+
curl -s "https://api.atris.ai/api/integrations/slack/users" -H "Authorization: Bearer $TOKEN"
|
|
320
|
+
```
|
package/atris/team/executor.md
CHANGED
package/atris/team/launcher.md
CHANGED
package/atris/team/navigator.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# navigator.md — Planner
|
|
2
2
|
|
|
3
3
|
> **Role:** Transform messy human intent into precise execution plans | **Source:** idea.md, MAP.md
|
|
4
|
+
> **Style:** Read `atris/PERSONA.md` for communication style.
|
|
4
5
|
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -151,6 +152,7 @@ Navigator creates validate.md with Status (v0 — planned) and Checks. The execu
|
|
|
151
152
|
6. **Free-flow works** — Even exploratory conversations go through this flow
|
|
152
153
|
|
|
153
154
|
**Before creating new feature:**
|
|
155
|
+
- Read `atris/lessons.md` for relevant patterns — if a past lesson applies, reference it as a constraint in idea.md
|
|
154
156
|
- Read atris/features/README.md
|
|
155
157
|
- Search keywords for similar features
|
|
156
158
|
- If exists: extend it, don't duplicate
|
package/atris/team/validator.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# validator.md — Reviewer (The Safety)
|
|
2
2
|
|
|
3
3
|
> **Role:** Validate execution, update docs, ensure quality | **Source:** build.md, MAP.md, code
|
|
4
|
+
> **Style:** Read `atris/PERSONA.md` for communication style.
|
|
4
5
|
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -144,4 +145,18 @@ One-line description
|
|
|
144
145
|
|
|
145
146
|
---
|
|
146
147
|
|
|
148
|
+
## Harvest Lessons
|
|
149
|
+
|
|
150
|
+
After validation, ask yourself: **did anything surprise me?** Something broke unexpectedly, worked differently than planned, or revealed a pattern worth remembering.
|
|
151
|
+
|
|
152
|
+
If yes, append to `atris/lessons.md`:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
- **[YYYY-MM-DD] [feature-name]** — (pass|fail) — One-line lesson
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If nothing surprised you, don't write anything. A clean build with no surprises isn't a lesson — it's the system working. Only capture what's genuinely useful for the next navigator reading this file.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
147
162
|
**Validator = The Safety. Ultrathink. Test. Approve only when perfect.**
|
package/atris.md
CHANGED
|
@@ -187,6 +187,22 @@ Specs loaded at activate from `team/*.md`
|
|
|
187
187
|
|
|
188
188
|
---
|
|
189
189
|
|
|
190
|
+
## PERSISTENCE
|
|
191
|
+
|
|
192
|
+
Context window = cache. Disk = truth. Route discoveries as they happen.
|
|
193
|
+
|
|
194
|
+
| You discover... | Write to... | Format |
|
|
195
|
+
|---------------------|----------------------|----------------------|
|
|
196
|
+
| Code location | MAP.md | file:line reference |
|
|
197
|
+
| New task | TODO.md | Task + exit condition |
|
|
198
|
+
| Decision / tradeoff | Journal → Notes | Timestamped line |
|
|
199
|
+
| Something learned | lessons.md | One-line lesson |
|
|
200
|
+
| Work finished | Journal → Completed | C#: description |
|
|
201
|
+
|
|
202
|
+
Don't batch. Don't wait for session end. Nothing important should live only in-context.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
190
206
|
## RULES
|
|
191
207
|
|
|
192
208
|
- 3-4 sentences max
|
|
@@ -194,6 +210,7 @@ Specs loaded at activate from `team/*.md`
|
|
|
194
210
|
- Check MAP.md before touching code
|
|
195
211
|
- Update journal after completing work
|
|
196
212
|
- Delete tasks when done (target: 0)
|
|
213
|
+
- Persist as you go (see PERSISTENCE)
|
|
197
214
|
|
|
198
215
|
---
|
|
199
216
|
|
package/bin/atris.js
CHANGED
|
@@ -203,6 +203,11 @@ function showHelp() {
|
|
|
203
203
|
console.log(' slack - Slack commands (channels)');
|
|
204
204
|
console.log(' integrations - Show integration status');
|
|
205
205
|
console.log('');
|
|
206
|
+
console.log('Skills:');
|
|
207
|
+
console.log(' skill list - Show all skills with compliance status');
|
|
208
|
+
console.log(' skill audit [name] - Validate skill against Anthropic guide');
|
|
209
|
+
console.log(' skill fix [name] - Auto-fix common compliance issues');
|
|
210
|
+
console.log('');
|
|
206
211
|
console.log('Other:');
|
|
207
212
|
console.log(' version - Show Atris version');
|
|
208
213
|
console.log(' help - Show this help');
|
|
@@ -308,11 +313,12 @@ const { statusAtris: statusCmd } = require('../commands/status');
|
|
|
308
313
|
const { analyticsAtris: analyticsCmd } = require('../commands/analytics');
|
|
309
314
|
const { cleanAtris: cleanCmd } = require('../commands/clean');
|
|
310
315
|
const { verifyAtris: verifyCmd } = require('../commands/verify');
|
|
316
|
+
const { skillCommand: skillCmd } = require('../commands/skill');
|
|
311
317
|
|
|
312
318
|
// Check if this is a known command or natural language input
|
|
313
319
|
const knownCommands = ['init', 'log', 'status', 'analytics', 'visualize', 'brainstorm', 'autopilot', 'plan', 'do', 'review',
|
|
314
320
|
'activate', 'agent', 'chat', 'login', 'logout', 'whoami', 'update', 'upgrade', 'version', 'help', 'next', 'atris',
|
|
315
|
-
'clean', 'verify', 'search',
|
|
321
|
+
'clean', 'verify', 'search', 'skill',
|
|
316
322
|
'gmail', 'calendar', 'twitter', 'slack', 'integrations'];
|
|
317
323
|
|
|
318
324
|
// Check if command is an atris.md spec file - triggers welcome visualization
|
|
@@ -790,6 +796,10 @@ if (command === 'init') {
|
|
|
790
796
|
integrationsStatus()
|
|
791
797
|
.then(() => process.exit(0))
|
|
792
798
|
.catch((err) => { console.error(err.message); process.exit(1); });
|
|
799
|
+
} else if (command === 'skill') {
|
|
800
|
+
const subcommand = process.argv[3];
|
|
801
|
+
const args = process.argv.slice(4);
|
|
802
|
+
skillCmd(subcommand, ...args);
|
|
793
803
|
} else {
|
|
794
804
|
console.log(`Unknown command: ${command}`);
|
|
795
805
|
console.log('Run "atris help" to see available commands');
|
|
@@ -2605,13 +2615,15 @@ async function atrisDevEntry(userInput = null) {
|
|
|
2605
2615
|
if (existingFeatures.length > 0) {
|
|
2606
2616
|
console.log(' Existing: ' + existingFeatures.join(', '));
|
|
2607
2617
|
}
|
|
2608
|
-
console.log(' NEW feature → atris/features/[name]/idea.md + build.md');
|
|
2618
|
+
console.log(' NEW feature → atris/features/[name]/idea.md + build.md + validate.md');
|
|
2609
2619
|
console.log(' EXISTING → Update that feature\'s docs');
|
|
2610
2620
|
console.log(' SIMPLE → TODO.md only');
|
|
2611
2621
|
console.log('');
|
|
2612
2622
|
console.log('STEP 3: Create/update docs');
|
|
2613
2623
|
console.log(' idea.md = intent (any format)');
|
|
2614
2624
|
console.log(' build.md = technical spec');
|
|
2625
|
+
console.log(' validate.md = proof it works (from _templates/validate.md.template)');
|
|
2626
|
+
console.log(' lessons.md = read past lessons before planning, write new ones after validating');
|
|
2615
2627
|
console.log('');
|
|
2616
2628
|
console.log('⛔ DO NOT execute — that\'s for "atris do"');
|
|
2617
2629
|
console.log('');
|
package/commands/init.js
CHANGED
|
@@ -373,6 +373,19 @@ function initAtris() {
|
|
|
373
373
|
console.log('✓ Created TODO.md placeholder');
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
+
// Create lessons.md (feedback loop for learning across features)
|
|
377
|
+
const lessonsFile = path.join(targetDir, 'lessons.md');
|
|
378
|
+
if (!fs.existsSync(lessonsFile)) {
|
|
379
|
+
fs.writeFileSync(lessonsFile, `# lessons.md — What We Learned
|
|
380
|
+
|
|
381
|
+
> Append-only. One line per lesson. Harvested by validator after every feature.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
`);
|
|
386
|
+
console.log('✓ Created lessons.md');
|
|
387
|
+
}
|
|
388
|
+
|
|
376
389
|
// Create logs directory and today's journal with bootstrap tasks
|
|
377
390
|
const logsDir = path.join(targetDir, 'logs');
|
|
378
391
|
const yearDir = path.join(logsDir, new Date().getFullYear().toString());
|