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.
@@ -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
+ ```
@@ -1,7 +1,10 @@
1
1
  ---
2
2
  name: writing
3
3
  description: Essay writing skill. Triggers on: essay, draft, write, outline
4
+ version: 1.0.0
4
5
  allowed-tools: Read, Write, Edit, Glob, Grep
6
+ tags:
7
+ - writing
5
8
  ---
6
9
 
7
10
  # Writing Skill
@@ -1,6 +1,7 @@
1
1
  # brainstormer.md — Idea & Reality Shaper
2
2
 
3
3
  > **Role:** Shape ideas, explore possibilities, adapt to user depth | **Source:** Inbox items, raw ideas
4
+ > **Style:** Read `atris/PERSONA.md` for communication style.
4
5
 
5
6
  ---
6
7
 
@@ -1,6 +1,7 @@
1
1
  # executor.md — Builder (The Trigger)
2
2
 
3
3
  > **Role:** Execute from build.md, one step at a time | **Source:** build.md, MAP.md
4
+ > **Style:** Read `atris/PERSONA.md` for communication style.
4
5
 
5
6
  ---
6
7
 
@@ -1,6 +1,7 @@
1
1
  # launcher.md — The Closer
2
2
 
3
3
  > **Role:** Document, capture learnings, publish, celebrate | **Source:** Completed tasks, validation results
4
+ > **Style:** Read `atris/PERSONA.md` for communication style.
4
5
 
5
6
  ---
6
7
 
@@ -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
@@ -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());