atris 3.56.0 → 3.56.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/atris/skills/engines/SKILL.md +11 -3
- package/atris/skills/x-search/SKILL.md +20 -1
- package/atris/skills/youtube/SKILL.md +51 -43
- package/bin/atris.js +134 -90
- package/commands/auth.js +6 -1
- package/commands/autopilot-front.js +29 -13
- package/commands/brainstorm.js +77 -476
- package/commands/business.js +13 -1
- package/commands/engine.js +7 -0
- package/commands/experiments.js +178 -0
- package/commands/fleet-report.js +2 -2
- package/commands/founder.js +12 -0
- package/commands/human-missions.js +64 -2
- package/commands/init.js +2 -35
- package/commands/integrations.js +100 -0
- package/commands/land.js +53 -23
- package/commands/later.js +52 -0
- package/commands/launchpad.js +45 -10
- package/commands/log.js +79 -30
- package/commands/mission.js +117 -22
- package/commands/next.js +153 -63
- package/commands/now.js +115 -38
- package/commands/recap.js +97 -4
- package/commands/run-front.js +20 -5
- package/commands/spaceship.js +52 -12
- package/commands/status.js +38 -7
- package/commands/task.js +56 -19
- package/commands/terminal.js +5 -5
- package/commands/workflow.js +19 -5
- package/commands/x-search.js +123 -13
- package/commands/youtube.js +941 -36
- package/lib/account-bound.js +7 -0
- package/lib/apply-gate.js +102 -0
- package/lib/config-guard.js +106 -0
- package/lib/context-gatherer.js +55 -8
- package/lib/engine-ask.js +16 -6
- package/lib/engine-registry.js +14 -4
- package/lib/first-minute.js +571 -26
- package/lib/known-commands.js +1 -1
- package/lib/pack-capabilities.js +13 -3
- package/lib/runner-command.js +5 -3
- package/lib/scratch-root.js +44 -0
- package/lib/workspace-scaffold.js +3 -1
- package/package.json +1 -1
- package/utils/auth.js +84 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: engines
|
|
3
3
|
description: "Dispatch work to an installed terminal agent or named Atris engine profile. Supports Atris Fast, Claude, Codex, Cursor, Fable, Composer, Haiku, Devin, Grok, and Antigravity (agy). Triggers on: use codex, use cursor, use devin, use grok, use agy, use antigravity, use fable, use claude, use atris, engine, dispatch to, worker agent, second opinion build."
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.1
|
|
5
5
|
tags:
|
|
6
6
|
- engines
|
|
7
7
|
- claude
|
|
@@ -28,6 +28,13 @@ One contract, ten live profiles. The orchestrator writes a bounded task prompt,
|
|
|
28
28
|
- build: `atris engine <name> <task-id>`
|
|
29
29
|
- switch: `atris engine <name>`
|
|
30
30
|
|
|
31
|
+
## Fable means Fable
|
|
32
|
+
|
|
33
|
+
Use `atris engine fable "<bounded question>"` for Fable's take. The canonical
|
|
34
|
+
profile pins `claude-fable-5`, gives deep Fable asks ten minutes by default,
|
|
35
|
+
and records the resolved model in the receipt. An explicit `--model` or
|
|
36
|
+
`--timeout` still wins.
|
|
37
|
+
|
|
31
38
|
## Raw binary fallback and debugging
|
|
32
39
|
|
|
33
40
|
Raw spawns are not the default because they skip Atris receipts, watch, and coaching.
|
|
@@ -38,7 +45,7 @@ Raw spawns are not the default because they skip Atris receipts, watch, and coac
|
|
|
38
45
|
| Claude | `claude -p "<prompt>"` | Uses the local Claude configuration. Add `--model opus` for maximum-depth review or `--model sonnet` for speed. |
|
|
39
46
|
| Codex | `codex exec --dangerously-bypass-approvals-and-sandbox -o <result-file> "<prompt>"` (run from the target repo/worktree; read-only research: `--sandbox read-only`) | Headless, exits when done — run it as a tracked background Bash task like the other engines and completion auto-wakes the session. Final answer lands in the `-o` file. Verified live 2026-08-11. Outside a git repo add `--skip-git-repo-check` or it exits 1. ONE-SHOT SESSIONS (`claude -p` workers): run codex in the FOREGROUND and wait — a one-shot session never wakes again, so backgrounding strands the result (observed 2026-08-11). The old plugin path (`codex-companion.mjs task --background`) is deprecated for dispatch: its job store never notifies the session (a finished result sat unread overnight, 2026-08-10) |
|
|
40
47
|
| Cursor | `cursor-agent --trust -p "<prompt>"` (run from the target repo) | Headless print mode; `--trust` required for non-interactive |
|
|
41
|
-
| Fable | `claude -p "<prompt>" --model
|
|
48
|
+
| Fable | `claude -p "<prompt>" --model claude-fable-5` | Raw fallback only. Prefer `atris engine fable` so the model, longer timeout, live log, and receipt stay honest. |
|
|
42
49
|
| Composer | `atris run "<objective>" --engine composer` | Fast navigator/executor profile routed through the installed `ax` binary. |
|
|
43
50
|
| Haiku | `claude -p "<prompt>" --model claude-haiku-4-5` | Fast validation and bounded read-only checks. |
|
|
44
51
|
| Devin | `devin -p --permission-mode dangerous -- "<prompt>"` (run from the target repo) | Default permission mode is read-only for writes — build work NEEDS `--permission-mode dangerous`, so only run it in an isolated worktree. Also `devin cloud` for sessions that outlive this machine. Supports `--model swe-1.7` |
|
|
@@ -65,7 +72,8 @@ Each engine CLI can pin a specific model. Current best picks:
|
|
|
65
72
|
|
|
66
73
|
| Engine | Flag | Best models today |
|
|
67
74
|
|--------|------|-------------------|
|
|
68
|
-
| Claude
|
|
75
|
+
| Claude | `--model opus` | `opus` follows the local Claude alias; use an explicit model identifier for reproducibility |
|
|
76
|
+
| Fable | `--model claude-fable-5` | Canonical Fable 5 route; `atris engine fable` pins it automatically |
|
|
69
77
|
| Devin | `--model swe-1.7` | `swe-1.7` (free right now: use it as the volume executor for parallel bounded slices), `swe-1.7-lightning` for speed |
|
|
70
78
|
| Cursor | `--model cursor-grok-4.6-xhigh` | `cursor-grok-4.6-xhigh` for second-opinion builds, `cursor-grok-4.6-high-fast` for quick pinned asks (answered in ~12s live 2026-08-12), `composer-2.5` for fast edits; parameterized Claude via `'claude-opus-4-8[effort=high]'`; `--list-models` shows the full menu |
|
|
71
79
|
| Composer | `--engine composer` | `composer 2.5` through the Atris profile |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: x-search
|
|
3
3
|
description: "X/Twitter search via xAI Grok API. Use when user wants to search tweets, monitor topics, find viral posts, or run social listening. Costs 5 credits per search. Triggers on x search, tweet search, twitter search, social listening, revenue intel, viral tweets."
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
tags:
|
|
6
6
|
- x-search
|
|
7
7
|
- social
|
|
@@ -12,6 +12,25 @@ tags:
|
|
|
12
12
|
|
|
13
13
|
> Drop this in `~/.claude/skills/x-search/SKILL.md` and Claude Code becomes your X/Twitter intelligence tool.
|
|
14
14
|
|
|
15
|
+
## Feature map
|
|
16
|
+
|
|
17
|
+
Hard path. Follow in order. Soft memory does not override this.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
login
|
|
21
|
+
|
|
|
22
|
+
x-search QUERY (5 credits)
|
|
23
|
+
|
|
|
24
|
+
write one Apply (claimable)
|
|
25
|
+
|
|
|
26
|
+
stop
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
1. Login: stored login, then `atris login --agent` if needed. Never paste tokens. Never `/auth/cli`.
|
|
30
|
+
2. Search: `atris x-search "QUERY"`. Always billed (5 credits). Empty or failed search refunds.
|
|
31
|
+
3. One Apply: name a product change plus a receipt that can fail. If missing, the CLI writes a fill-this stub and a next-line. Search still exits 0.
|
|
32
|
+
4. Stop. Empty or failed search does not owe an Apply.
|
|
33
|
+
|
|
15
34
|
## Customer path (preferred)
|
|
16
35
|
|
|
17
36
|
Logged-in customers should use the CLI. Same auth and billing as `atris youtube process` (5 credits).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: youtube
|
|
3
|
-
description: "YouTube discovery and learning.
|
|
4
|
-
version: 2.
|
|
3
|
+
description: "YouTube discovery and learning. Get watch permalinks with atris youtube search QUERY (free, local ytsearch/yt-dlp). On 429 the CLI already retries; use cached rows if printed, else STOP. Never run --paid after a 429. --paid only when the user explicitly asked to buy permalinks (5 credits). After a URL is picked, atris youtube notes URL (free, ephemeral unless --save). atris youtube process only to store knowledge (5 credits). Never paste tokens. Never /auth/cli. Mint with atris login --agent from a stored login. Never summarize a video from model memory. Triggers on: youtube search, find videos, paid youtube search, any youtube.com or youtu.be link, youtube, video, watch this, notes on this."
|
|
4
|
+
version: 2.11.0
|
|
5
5
|
tags:
|
|
6
6
|
- youtube
|
|
7
7
|
- research
|
|
@@ -11,47 +11,56 @@ tags:
|
|
|
11
11
|
|
|
12
12
|
# YouTube Skill
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Feature map
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
- **Paid search (5 credits)** → `atris youtube search --paid "<query>"`. Posts `/youtube/search` with the stored token or a youtube-scope agent mint. Prints watch permalinks, titles, and credits. Use this when the customer wants to buy permalinks the same way as `atris x-search`. Do not replace free search with this.
|
|
18
|
-
- **Notes / learning (free)** → `atris youtube notes <url>`. Local captions + a fast engine, about 30 seconds, quotes verified against the transcript. Use when the goal is to learn from a video you already have.
|
|
19
|
-
- **Process / product (5 credits)** → `atris youtube process <url>`. Credits-billed cloud knowledge store. Use when a customer/agent needs the video stored as Atris knowledge.
|
|
16
|
+
Hard path. Follow in order. Soft memory does not override this.
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
```
|
|
19
|
+
search QUERY (free)
|
|
20
|
+
|
|
|
21
|
+
429 --> CLI already retried once
|
|
22
|
+
--> cached rows printed? use them
|
|
23
|
+
--> rate-limit sentence printed? STOP
|
|
24
|
+
do not run --paid
|
|
25
|
+
|
|
|
26
|
+
pick a URL --> notes URL (free, ephemeral unless --save)
|
|
27
|
+
| --save files the brief + apply stub
|
|
28
|
+
| or teach URL [--section N] (one chapter: claim numbers, named mechanisms, one check; free unless --save)
|
|
29
|
+
|
|
|
30
|
+
write one Apply (claimable) before process
|
|
31
|
+
|
|
|
32
|
+
store knowledge? --> process URL (5 credits)
|
|
33
|
+
|
|
34
|
+
--paid QUERY only if the user asked to buy permalinks
|
|
35
|
+
login: atris login --agent from a stored login
|
|
36
|
+
never paste tokens, never /auth/cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
1. Get watch permalinks: `atris youtube search QUERY` (free).
|
|
40
|
+
2. If 429: wait/retry is already in the CLI. If it prints cached rows, use those. If it prints `youtube rate-limited local search. do not use --paid as a fallback; retry later.`, STOP. Do not run `--paid`.
|
|
41
|
+
3. `--paid` only when the user explicitly asked to buy permalinks. The CLI hard-refuses `--paid` when the free cache still has a fresh same-query hit.
|
|
42
|
+
4. `atris youtube notes URL` after a URL is picked (free). Notes is ephemeral unless `--save`.
|
|
43
|
+
5. Write one Apply (change + receipt) before `atris youtube process`. Process still requires a filled Apply (so you `--save`, fill Apply, then process).
|
|
44
|
+
6. Never paste tokens. Never `/auth/cli`. Mint with `atris login --agent` from a stored login.
|
|
45
|
+
|
|
46
|
+
If the user says "find videos", "search youtube", or "get youtube links" → search. If they say "learn from", "notes on", "alpha", or "rabbit hole" → notes. If they say "process", "store", "add to knowledge" → process. "Buy permalinks" or "paid search" is the only ask that unlocks `--paid`.
|
|
22
47
|
|
|
23
48
|
Never summarize a video from model memory; that is fabrication.
|
|
24
49
|
|
|
25
|
-
## Bootstrap
|
|
50
|
+
## Bootstrap
|
|
51
|
+
|
|
52
|
+
Search and notes need no login. Paid search and process need a stored login, then `atris login --agent`. Never print credentials. Never `/auth/cli`.
|
|
26
53
|
|
|
27
54
|
```bash
|
|
28
55
|
#!/bin/bash
|
|
29
56
|
set -e
|
|
30
57
|
|
|
31
|
-
# 1. Check atris CLI
|
|
32
58
|
if ! command -v atris &> /dev/null; then
|
|
33
59
|
echo "Installing atris CLI..."
|
|
34
60
|
npm install -g atris
|
|
35
61
|
fi
|
|
36
62
|
|
|
37
|
-
|
|
38
|
-
if [ ! -f ~/.atris/credentials.json ]; then
|
|
39
|
-
echo "Not logged in. Search and notes still work. Process needs: atris login"
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# 3. Extract token when present
|
|
43
|
-
if [ -f ~/.atris/credentials.json ]; then
|
|
44
|
-
if command -v node &> /dev/null; then
|
|
45
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
46
|
-
elif command -v python3 &> /dev/null; then
|
|
47
|
-
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
|
|
48
|
-
elif command -v jq &> /dev/null; then
|
|
49
|
-
TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
|
|
50
|
-
fi
|
|
51
|
-
export ATRIS_TOKEN="$TOKEN"
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
echo "Ready. YouTube skill active (search + notes free; process 5 credits)."
|
|
63
|
+
echo "Ready. Feature map: free search, 429 cache-or-stop, notes, then process."
|
|
55
64
|
```
|
|
56
65
|
|
|
57
66
|
---
|
|
@@ -66,14 +75,18 @@ atris youtube search "MCP agents" --json
|
|
|
66
75
|
|
|
67
76
|
Uses `ytsearch` on PATH when present, else bundled `scripts/det/ytsearch`, else `yt-dlp --flat-playlist --print` with `ytsearchN:`. No credits. No `/agent/process_youtube` call.
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
On 429 the CLI retries once, then serves `~/.atris/youtube-search-cache.json` if the same query is younger than one hour. If it prints the rate-limit sentence, stop. Do not run `--paid`.
|
|
79
|
+
|
|
80
|
+
## Paid search (5 credits, opt-in buy only)
|
|
81
|
+
|
|
82
|
+
Only when the user explicitly asked to buy permalinks. A 429 or a missing cache is not that ask.
|
|
70
83
|
|
|
71
84
|
```bash
|
|
72
85
|
atris youtube search --paid "MCP agents 2026"
|
|
73
86
|
atris youtube search --paid "MCP agents" --limit 10
|
|
74
87
|
```
|
|
75
88
|
|
|
76
|
-
Requires login
|
|
89
|
+
Requires a stored login, then `atris login --agent`. The CLI mints a youtube-scope agent token from disk the same way as `atris youtube process` and `atris x-search`. Never `/auth/cli`. Never paste tokens. Prints `title | watch permalink` plus credits. Empty or failed searches refund.
|
|
77
90
|
|
|
78
91
|
Line contract:
|
|
79
92
|
|
|
@@ -90,10 +103,7 @@ title | channel | duration | views | upload_date | https://youtu.be/ID
|
|
|
90
103
|
Base: `https://api.atris.ai/api`
|
|
91
104
|
Auth: `-H "Authorization: Bearer $TOKEN"`
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
96
|
-
```
|
|
106
|
+
Do not extract or paste tokens. The CLI reads the stored login. Agents mint with `atris login --agent`.
|
|
97
107
|
|
|
98
108
|
### Process a Video
|
|
99
109
|
```bash
|
|
@@ -203,7 +213,7 @@ Two layers, never mixed. The reply the person reads is flowing prose: ideas, spe
|
|
|
203
213
|
|
|
204
214
|
`atris youtube search` shells to local ytsearch/yt-dlp and never hits the Atris API.
|
|
205
215
|
|
|
206
|
-
`atris youtube search --paid` posts `{query, limit}` to `/youtube/search` with bearer auth. Agent tokens need the youtube scope.
|
|
216
|
+
`atris youtube search --paid` posts `{query, limit}` to `/youtube/search` with bearer auth. Agent tokens need the youtube scope. This is an opt-in buy, not a 429 fallback.
|
|
207
217
|
|
|
208
218
|
`atris youtube` process first tries local transcript extraction with `yt-dlp`. It sends timestamped `transcript_text` to `/agent/process_youtube` with `cache_transcript=false`. If local transcript processing fails with a retryable error, it falls back to cloud video processing. Use `--json` to inspect `metadata.processing_method` and `metadata.transcript_source`.
|
|
209
219
|
|
|
@@ -225,35 +235,33 @@ Two layers, never mixed. The reply the person reads is flowing prose: ideas, spe
|
|
|
225
235
|
|
|
226
236
|
| Error | Meaning | Fix |
|
|
227
237
|
|-------|---------|-----|
|
|
228
|
-
| `401` | Token expired/invalid | `atris login --
|
|
238
|
+
| `401` | Token expired/invalid | `atris login --agent` from a stored login |
|
|
229
239
|
| `402` | Not enough credits | Check balance, purchase at atris.ai |
|
|
230
240
|
| `400` | Invalid YouTube URL | Check URL format |
|
|
231
241
|
| `502` | Transcript or cloud processing failed | Retry; credits auto-refunded when backend fails |
|
|
232
242
|
| search exit 2 | ytsearch/yt-dlp missing or no results | Install yt-dlp, or put ytsearch on PATH |
|
|
233
|
-
| search 429 | YouTube rate-limited local search |
|
|
243
|
+
| search 429 | YouTube rate-limited local search | CLI already retried; use cached rows if printed; if the rate-limit sentence prints, STOP; do not use --paid |
|
|
234
244
|
|
|
235
245
|
---
|
|
236
246
|
|
|
237
247
|
## Quick Reference
|
|
238
248
|
|
|
239
249
|
```bash
|
|
240
|
-
# Setup
|
|
250
|
+
# Setup: human stores a login, then agents mint. never /auth/cli
|
|
241
251
|
npm install -g atris && atris login
|
|
252
|
+
atris login --agent
|
|
242
253
|
|
|
243
254
|
# Free: discover videos
|
|
244
255
|
atris youtube search "MCP agents 2026"
|
|
245
256
|
atris youtube search "MCP agents" --limit 10
|
|
246
257
|
|
|
247
|
-
# Paid:
|
|
258
|
+
# Paid: only if the user asked to buy permalinks (5 credits). never a 429 fallback
|
|
248
259
|
atris youtube search --paid "MCP agents 2026"
|
|
249
260
|
|
|
250
261
|
# Free: notes on a URL you already have
|
|
251
262
|
atris youtube notes "https://youtu.be/VIDEO_ID"
|
|
252
263
|
|
|
253
|
-
#
|
|
254
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
255
|
-
|
|
256
|
-
# Process a video (5 credits)
|
|
264
|
+
# Process a video (5 credits). different store from paid search
|
|
257
265
|
atris youtube process "https://youtube.com/watch?v=..." --query "Create a outline (flowing, idea-first) and action brief"
|
|
258
266
|
|
|
259
267
|
# Process + store to agent knowledge
|
package/bin/atris.js
CHANGED
|
@@ -47,7 +47,7 @@ const {
|
|
|
47
47
|
requireAccountBound,
|
|
48
48
|
refuseAccountGlobal,
|
|
49
49
|
} = require('../lib/account-bound');
|
|
50
|
-
const { isHelpToken, argsWantHelp } = require('../lib/noninteractive');
|
|
50
|
+
const { isHelpToken, argsWantHelp, hasYesFlag } = require('../lib/noninteractive');
|
|
51
51
|
|
|
52
52
|
// State detection for smart default
|
|
53
53
|
const { detectWorkspaceState, loadContext } = require('../lib/state-detection');
|
|
@@ -56,12 +56,20 @@ const {
|
|
|
56
56
|
createStarterTask,
|
|
57
57
|
shouldGatherContext,
|
|
58
58
|
isAtrisMetaQuestion,
|
|
59
|
+
isFlagLikeAnswer,
|
|
59
60
|
renderPrompt: renderContextGathererPrompt,
|
|
60
61
|
} = require('../lib/context-gatherer');
|
|
61
62
|
const {
|
|
62
63
|
buildFirstMinute,
|
|
64
|
+
firstTalkJson,
|
|
65
|
+
folderName,
|
|
63
66
|
freshMinuteJson,
|
|
64
67
|
isBareAtrisFlag,
|
|
68
|
+
isFirstTalkLine,
|
|
69
|
+
isLeftoverVerbLook,
|
|
70
|
+
listUserVisibleWork,
|
|
71
|
+
personName,
|
|
72
|
+
renderFirstTalk,
|
|
65
73
|
shouldAutoInitFresh,
|
|
66
74
|
} = require('../lib/first-minute');
|
|
67
75
|
|
|
@@ -203,7 +211,7 @@ function parseNaturalEntryArgs(args = []) {
|
|
|
203
211
|
};
|
|
204
212
|
}
|
|
205
213
|
|
|
206
|
-
function applyRunnerFlags(args) {
|
|
214
|
+
function applyRunnerFlags(args, options = {}) {
|
|
207
215
|
// --engine <name> is the operator-facing spelling of --runner-profile:
|
|
208
216
|
// one flag rents a specific intelligence for this run.
|
|
209
217
|
const engineFlag = readOptionArg(args, '--engine');
|
|
@@ -243,6 +251,9 @@ function applyRunnerFlags(args) {
|
|
|
243
251
|
process.env.ATRIS_RUNNER_MODEL = runnerModel;
|
|
244
252
|
process.env.ATRIS_CLAUDE_MODEL = runnerModel;
|
|
245
253
|
}
|
|
254
|
+
// Talk-only and unbound scratch still validate --engine / --runner-profile.
|
|
255
|
+
// They skip this seed so resolveDefaultEngine cannot mint engines.json.
|
|
256
|
+
if (options.seed === false) return;
|
|
246
257
|
// No per-run choice and no env: the workspace's saved engine
|
|
247
258
|
// (.atris/engine.json, written by `atris engine <name>`) becomes the
|
|
248
259
|
// profile for every loop spawn. For the loop commands themselves, fall all
|
|
@@ -484,17 +495,14 @@ function showStartHelp() {
|
|
|
484
495
|
}
|
|
485
496
|
|
|
486
497
|
function showHelpShort() {
|
|
487
|
-
console.log('atris: you say what you want
|
|
488
|
-
console.log('');
|
|
489
|
-
console.log('
|
|
490
|
-
console.log(' atris
|
|
491
|
-
console.log(' atris
|
|
492
|
-
console.log(' atris
|
|
493
|
-
console.log(' atris
|
|
494
|
-
console.log(' atris
|
|
495
|
-
console.log(' atris review validate');
|
|
496
|
-
console.log(' atris recap spoken recap of what landed');
|
|
497
|
-
console.log(' atris mission status active goals + next move');
|
|
498
|
+
console.log('atris: you say what you want. already won. one next step.');
|
|
499
|
+
console.log('');
|
|
500
|
+
console.log(' atris "what do you want here?" empty folder');
|
|
501
|
+
console.log(' atris later "..." remember without a room');
|
|
502
|
+
console.log(' atris do work already here');
|
|
503
|
+
console.log(' atris spaceship Keep working for a few hours');
|
|
504
|
+
console.log(' atris autopilot Keep working until you stop');
|
|
505
|
+
console.log(' atris mission the one goal');
|
|
498
506
|
console.log('');
|
|
499
507
|
console.log('More: atris help --all · machine list: atris help --json');
|
|
500
508
|
}
|
|
@@ -506,7 +514,7 @@ function helpCatalog() {
|
|
|
506
514
|
{ name: 'review', summary: 'validate work and capture learnings', json: false, interactive_risk: 'low' },
|
|
507
515
|
{ name: 'recap', summary: 'spoken recap of what your team did', json: true, interactive_risk: 'low' },
|
|
508
516
|
{ name: 'mission', summary: 'durable goal + owner + verifier + tick', json: true, interactive_risk: 'medium' },
|
|
509
|
-
{ name: 'log', summary: 'append an idea to today inbox (or --repl)', json:
|
|
517
|
+
{ name: 'log', summary: 'append an idea to today inbox (or --repl)', json: true, interactive_risk: 'low' },
|
|
510
518
|
{ name: 'wish', summary: 'headless inbox / mission intake', json: true, interactive_risk: 'low' },
|
|
511
519
|
{ name: 'learn', summary: 'structured project learnings', json: false, interactive_risk: 'low' },
|
|
512
520
|
{ name: 'activate', summary: 'load atris context for this session', json: false, interactive_risk: 'low' },
|
|
@@ -517,38 +525,16 @@ function helpCatalog() {
|
|
|
517
525
|
}
|
|
518
526
|
|
|
519
527
|
function showHelpAll() {
|
|
528
|
+
console.log('you say what you want. already won. one next step.');
|
|
520
529
|
console.log('');
|
|
521
|
-
console.log('
|
|
522
|
-
console.log('atris');
|
|
523
|
-
console.log('
|
|
524
|
-
console.log('
|
|
525
|
-
console.log('');
|
|
526
|
-
console.log('
|
|
527
|
-
console.log('');
|
|
528
|
-
console.log('
|
|
529
|
-
console.log(' npx atris same after a local install');
|
|
530
|
-
console.log(' 2. say what you want built, checked, or researched');
|
|
531
|
-
console.log(' 3. atris files the work, then you review');
|
|
532
|
-
console.log('');
|
|
533
|
-
console.log('Common invocations:');
|
|
534
|
-
console.log(' atris "<request>" one isolated change, then Review');
|
|
535
|
-
console.log(' atris "<request>" --verify "<cmd>" --json');
|
|
536
|
-
console.log(' atris init [--yes] scaffold this project');
|
|
537
|
-
console.log(' npx atris init [--yes] same after a local install');
|
|
538
|
-
console.log(' atris mission status current mission + next move');
|
|
539
|
-
console.log(' atris task ready <id> --proof "..."');
|
|
540
|
-
console.log(' atris computer');
|
|
541
|
-
console.log(' atris engine validate latest');
|
|
542
|
-
console.log(' atris playbook workspace style rules and paired trials');
|
|
543
|
-
console.log(' atris business init "My Company"');
|
|
544
|
-
console.log(' atris run');
|
|
545
|
-
console.log(' atris drill');
|
|
546
|
-
console.log(' atris status');
|
|
547
|
-
console.log(' atris soul');
|
|
548
|
-
console.log(' atris fleet status');
|
|
549
|
-
console.log(' ask/stop/ready see atris mission and atris task ready');
|
|
550
|
-
console.log('');
|
|
551
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
530
|
+
console.log(' atris later "..." remember without a room');
|
|
531
|
+
console.log(' atris do work already here');
|
|
532
|
+
console.log(' atris spaceship Keep working for a few hours');
|
|
533
|
+
console.log(' atris autopilot Keep working until you stop');
|
|
534
|
+
console.log(' atris mission the one goal');
|
|
535
|
+
console.log(' atris recap what got done');
|
|
536
|
+
console.log(' atris review check the work');
|
|
537
|
+
console.log(' atris stop stop the live goal');
|
|
552
538
|
console.log('');
|
|
553
539
|
console.log('Atris Computers:');
|
|
554
540
|
console.log(' Owner = User | Business');
|
|
@@ -649,6 +635,8 @@ function showHelpAll() {
|
|
|
649
635
|
console.log(' experiments init [slug] - Prepare atris/experiments/ or scaffold a pack');
|
|
650
636
|
console.log(' experiments validate - Validate experiment packs');
|
|
651
637
|
console.log(' experiments run <slug> - Execute a pack or record an Endstate receipt');
|
|
638
|
+
console.log(' experiments keep <slug> - Keep a pack only when measure.py moves 0 to 1');
|
|
639
|
+
console.log(' experiments revert <slug> - Run a pack reset.py after a refused keep');
|
|
652
640
|
console.log(' experiments benchmark [m] - Run validate/runtime experiment benchmarks');
|
|
653
641
|
console.log(' bench - run core benchmark gates');
|
|
654
642
|
console.log('');
|
|
@@ -765,7 +753,7 @@ function showHelpAll() {
|
|
|
765
753
|
console.log('');
|
|
766
754
|
console.log('Other:');
|
|
767
755
|
console.log(' version - Show Atris version');
|
|
768
|
-
console.log(' help -
|
|
756
|
+
console.log(' help - you say what you want (help --all for every command)');
|
|
769
757
|
console.log('');
|
|
770
758
|
console.log('Tip: Just run "atris" to get started');
|
|
771
759
|
console.log('');
|
|
@@ -1344,13 +1332,13 @@ function printFirstUseNext() {
|
|
|
1344
1332
|
console.log(`Then: ${firstUseCommand()}`);
|
|
1345
1333
|
}
|
|
1346
1334
|
|
|
1347
|
-
function runMinimalInit() {
|
|
1335
|
+
function runMinimalInit({ silent = false } = {}) {
|
|
1348
1336
|
const script = process.argv[1] || path.join(__dirname, 'atris.js');
|
|
1349
1337
|
const result = spawnSync(process.execPath, [script, 'init', '--minimal', '--yes'], {
|
|
1350
1338
|
cwd: process.cwd(),
|
|
1351
1339
|
env: process.env,
|
|
1352
1340
|
encoding: 'utf8',
|
|
1353
|
-
stdio: 'inherit',
|
|
1341
|
+
stdio: silent ? ['ignore', 'pipe', 'pipe'] : 'inherit',
|
|
1354
1342
|
});
|
|
1355
1343
|
return Number.isInteger(result.status) ? result.status : 1;
|
|
1356
1344
|
}
|
|
@@ -1366,16 +1354,56 @@ async function interactiveEntry(userInput, options = {}) {
|
|
|
1366
1354
|
const workspaceDir = process.cwd();
|
|
1367
1355
|
const state = detectWorkspaceState(workspaceDir);
|
|
1368
1356
|
|
|
1369
|
-
// Fresh folder is
|
|
1357
|
+
// Fresh folder is a conversation, not a scaffold form.
|
|
1370
1358
|
if (state.state === 'fresh') {
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1359
|
+
const request = String(userInput || '').trim();
|
|
1360
|
+
const room = folderName(workspaceDir);
|
|
1361
|
+
const who = personName();
|
|
1362
|
+
if (!request) {
|
|
1363
|
+
if (options.asJson) {
|
|
1364
|
+
console.log(JSON.stringify(freshMinuteJson(room, listUserVisibleWork(workspaceDir), { root: workspaceDir }), null, 2));
|
|
1365
|
+
return 2;
|
|
1366
|
+
}
|
|
1367
|
+
if (shouldAutoInitFresh(process.argv.slice(2))) {
|
|
1368
|
+
return runMinimalInit();
|
|
1369
|
+
}
|
|
1370
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1371
|
+
return 0;
|
|
1374
1372
|
}
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1373
|
+
if (isLeftoverVerbLook(request)) {
|
|
1374
|
+
if (options.asJson) {
|
|
1375
|
+
console.log(JSON.stringify(freshMinuteJson(room, listUserVisibleWork(workspaceDir), { root: workspaceDir }), null, 2));
|
|
1376
|
+
return 2;
|
|
1377
|
+
}
|
|
1378
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1379
|
+
return 0;
|
|
1377
1380
|
}
|
|
1378
|
-
|
|
1381
|
+
if (!isFirstTalkLine(request) && isAtrisMetaQuestion(request)) {
|
|
1382
|
+
if (options.asJson) {
|
|
1383
|
+
console.log(JSON.stringify({
|
|
1384
|
+
schema: 'atris.overview.v1',
|
|
1385
|
+
ok: true,
|
|
1386
|
+
product: 'Atris',
|
|
1387
|
+
}, null, 2));
|
|
1388
|
+
return 0;
|
|
1389
|
+
}
|
|
1390
|
+
printAtrisOverview();
|
|
1391
|
+
return 0;
|
|
1392
|
+
}
|
|
1393
|
+
if (isFlagLikeAnswer(request)) {
|
|
1394
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1395
|
+
return 0;
|
|
1396
|
+
}
|
|
1397
|
+
const initStatus = runMinimalInit({ silent: true });
|
|
1398
|
+
if (initStatus !== 0) return initStatus;
|
|
1399
|
+
saveContextProfile(workspaceDir, request, { source: 'first_talk' });
|
|
1400
|
+
const starter = createStarterTask(workspaceDir, request);
|
|
1401
|
+
if (options.asJson) {
|
|
1402
|
+
console.log(JSON.stringify(firstTalkJson({ starter, person: who, folder: room }), null, 2));
|
|
1403
|
+
return 0;
|
|
1404
|
+
}
|
|
1405
|
+
console.log('');
|
|
1406
|
+
console.log(renderFirstTalk({ person: who, folder: room, starter }));
|
|
1379
1407
|
return 0;
|
|
1380
1408
|
}
|
|
1381
1409
|
|
|
@@ -1921,18 +1949,14 @@ if (command === 'init') {
|
|
|
1921
1949
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1922
1950
|
} else if (command === 'land') {
|
|
1923
1951
|
// landCommand can throw synchronously on empty repos; wrap so callers get a
|
|
1924
|
-
// one-line
|
|
1952
|
+
// one-line sentence instead of an uncaught stack from Promise.resolve(fn()).
|
|
1925
1953
|
Promise.resolve()
|
|
1926
1954
|
.then(() => require('../commands/land').landCommand(process.argv.slice(3)))
|
|
1927
|
-
.then((code) => process.exit(code
|
|
1955
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1928
1956
|
.catch((err) => {
|
|
1929
|
-
const msg = String(err && err.message || err || '');
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
} else {
|
|
1933
|
-
console.error(`land: ${msg}`);
|
|
1934
|
-
}
|
|
1935
|
-
process.exit(1);
|
|
1957
|
+
const msg = String(err && err.message || err || 'land could not run').split('\n')[0];
|
|
1958
|
+
console.log(msg);
|
|
1959
|
+
process.exit(2);
|
|
1936
1960
|
});
|
|
1937
1961
|
} else if (command === 'caretaker') {
|
|
1938
1962
|
Promise.resolve(require('../commands/caretaker').caretakerCommand(process.argv.slice(3)))
|
|
@@ -2035,7 +2059,6 @@ if (command === 'init') {
|
|
|
2035
2059
|
} else if (command === 'log') {
|
|
2036
2060
|
const logArgs = process.argv.slice(3);
|
|
2037
2061
|
const subcommand = logArgs[0];
|
|
2038
|
-
const positional = logArgs.filter((arg) => !String(arg).startsWith('-'));
|
|
2039
2062
|
if (subcommand === 'sync') {
|
|
2040
2063
|
require('../commands/log-sync').logSyncAtris()
|
|
2041
2064
|
.then(() => process.exit(0))
|
|
@@ -2044,24 +2067,16 @@ if (command === 'init') {
|
|
|
2044
2067
|
process.exit(1);
|
|
2045
2068
|
});
|
|
2046
2069
|
} else if (subcommand === '--help' || subcommand === '-h' || subcommand === 'help') {
|
|
2047
|
-
console.log('Usage: atris log ["note"] | --repl | sync |
|
|
2070
|
+
console.log('Usage: atris log ["note"] [--json] | --repl | sync | help');
|
|
2048
2071
|
console.log('');
|
|
2049
2072
|
console.log(' atris log "an idea" Append a note to today\'s ## Inbox');
|
|
2073
|
+
console.log(' atris log text One word still lands in Inbox. No live business required');
|
|
2074
|
+
console.log(' atris log "an idea" --json');
|
|
2050
2075
|
console.log(' atris log --repl Open today\'s journal REPL');
|
|
2051
2076
|
console.log(' atris log Open the REPL (needs a terminal)');
|
|
2052
2077
|
console.log(' atris log sync Sync the local journal to cloud');
|
|
2053
|
-
console.log(' atris log <slug> Show business log history (single slug token)');
|
|
2054
2078
|
console.log(' atris wish "..." Headless inbox write; add --json --no-mission for agents');
|
|
2055
2079
|
process.exit(0);
|
|
2056
|
-
} else if (
|
|
2057
|
-
positional.length === 1
|
|
2058
|
-
&& !logArgs.includes('--repl')
|
|
2059
|
-
&& /^[a-z0-9][a-z0-9_-]{0,63}$/i.test(positional[0])
|
|
2060
|
-
) {
|
|
2061
|
-
// Business log: atris log <business-slug> (single slug token only)
|
|
2062
|
-
require('../commands/context-sync').businessLog(positional[0])
|
|
2063
|
-
.then(() => process.exit(0))
|
|
2064
|
-
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2065
2080
|
} else {
|
|
2066
2081
|
logCmd();
|
|
2067
2082
|
}
|
|
@@ -2084,13 +2099,14 @@ if (command === 'init') {
|
|
|
2084
2099
|
}
|
|
2085
2100
|
} else if (command === 'now') {
|
|
2086
2101
|
const args = process.argv.slice(3);
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
process.exit(0);
|
|
2090
|
-
}
|
|
2091
|
-
require('../commands/now').nowAtris(args);
|
|
2102
|
+
const nowCode = require('../commands/now').nowAtris(args);
|
|
2103
|
+
process.exit(Number.isInteger(nowCode) ? nowCode : 0);
|
|
2092
2104
|
} else if (command === 'recap') {
|
|
2093
|
-
require('../commands/recap').recapAtris(process.argv.slice(3));
|
|
2105
|
+
const recapCode = require('../commands/recap').recapAtris(process.argv.slice(3));
|
|
2106
|
+
if (Number.isInteger(recapCode)) process.exit(recapCode);
|
|
2107
|
+
} else if (command === 'later') {
|
|
2108
|
+
const laterCode = require('../commands/later').laterAtris(process.argv.slice(3));
|
|
2109
|
+
process.exit(Number.isInteger(laterCode) ? laterCode : 0);
|
|
2094
2110
|
} else if (command === 'activate') {
|
|
2095
2111
|
const args = process.argv.slice(3);
|
|
2096
2112
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
@@ -2431,7 +2447,14 @@ if (command === 'init') {
|
|
|
2431
2447
|
process.exit(0);
|
|
2432
2448
|
}
|
|
2433
2449
|
|
|
2434
|
-
|
|
2450
|
+
const { isUnboundScratchFolder } = require('../lib/scratch-root');
|
|
2451
|
+
const { runObjective, runMissionFront } = require('../commands/run-front');
|
|
2452
|
+
const runTalkOnly = !runObjective(args) && !hasYesFlag(args) && !args.includes('--legacy');
|
|
2453
|
+
// Flag validation always runs. The engine-registry seed is what mints
|
|
2454
|
+
// .atris/state/engines.json, so first-talk and unbound scratch skip only that.
|
|
2455
|
+
applyRunnerFlags(args, {
|
|
2456
|
+
seed: !runTalkOnly && !isUnboundScratchFolder(process.cwd()),
|
|
2457
|
+
});
|
|
2435
2458
|
|
|
2436
2459
|
if (args.includes('--legacy')) {
|
|
2437
2460
|
const legacyArgs = args.filter(a => a !== '--legacy');
|
|
@@ -2451,7 +2474,7 @@ if (command === 'init') {
|
|
|
2451
2474
|
process.exit(1);
|
|
2452
2475
|
});
|
|
2453
2476
|
} else {
|
|
2454
|
-
|
|
2477
|
+
runMissionFront(args)
|
|
2455
2478
|
.then((code) => process.exit(code || 0))
|
|
2456
2479
|
.catch((error) => {
|
|
2457
2480
|
console.error(`\u2717 Run failed: ${error.message || error}`);
|
|
@@ -2463,7 +2486,21 @@ if (command === 'init') {
|
|
|
2463
2486
|
process.exit(code);
|
|
2464
2487
|
} else if (command === 'autopilot') {
|
|
2465
2488
|
const args = process.argv.slice(3);
|
|
2466
|
-
|
|
2489
|
+
const { isUnboundScratchFolder, refuseUnboundScratch } = require('../lib/scratch-root');
|
|
2490
|
+
const { resolveWorkspaceRoot } = require('../lib/mission-root');
|
|
2491
|
+
const autopilotRoot = resolveWorkspaceRoot(process.cwd());
|
|
2492
|
+
const autopilotHelp = argsWantHelp(args) || args[0] === 'help';
|
|
2493
|
+
const autopilotControl = args[0] === 'stop' || args[0] === 'status';
|
|
2494
|
+
const autopilotJsonPlan = args.includes('--json') && !args.includes('--yes') && !args.includes('-y');
|
|
2495
|
+
const autopilotTalkOnly = !hasYesFlag(args) && !args.includes('--auto') && !args.includes('--legacy');
|
|
2496
|
+
// applyRunnerFlags seeds .atris/state/engines.json. Help, stop/status, JSON
|
|
2497
|
+
// plan, and an unbound scratch talk must not mint a room. --yes is not an unlock.
|
|
2498
|
+
if (!autopilotHelp && !autopilotControl && !autopilotJsonPlan && !autopilotTalkOnly && isUnboundScratchFolder(autopilotRoot)) {
|
|
2499
|
+
process.exit(refuseUnboundScratch());
|
|
2500
|
+
}
|
|
2501
|
+
if (!autopilotHelp) {
|
|
2502
|
+
applyRunnerFlags(args, { seed: !isUnboundScratchFolder(autopilotRoot) });
|
|
2503
|
+
}
|
|
2467
2504
|
|
|
2468
2505
|
if (args.includes('--legacy')) {
|
|
2469
2506
|
const legacyArgs = args.filter(a => a !== '--legacy');
|
|
@@ -2739,8 +2776,9 @@ if (command === 'init') {
|
|
|
2739
2776
|
const raw = process.argv.slice(3);
|
|
2740
2777
|
const { gmailCommand, extractGmailMailboxAccount } = require('../commands/integrations');
|
|
2741
2778
|
const mailbox = extractGmailMailboxAccount(raw);
|
|
2742
|
-
|
|
2743
|
-
|
|
2779
|
+
// Mailbox --account <id> is a selector, not the workspace opt-in.
|
|
2780
|
+
// Scratch folders refuse every gmail verb the same way as slack/inbox.
|
|
2781
|
+
const gate = requireAccountBound(mailbox.args.filter((arg) => arg !== '--account'));
|
|
2744
2782
|
if (!gate.ok) {
|
|
2745
2783
|
process.exit(refuseAccountGlobal());
|
|
2746
2784
|
return;
|
|
@@ -2775,9 +2813,15 @@ if (command === 'init') {
|
|
|
2775
2813
|
} else if (command === 'slack') {
|
|
2776
2814
|
{
|
|
2777
2815
|
const raw = process.argv.slice(3);
|
|
2778
|
-
const
|
|
2779
|
-
|
|
2780
|
-
|
|
2816
|
+
const { slackCommand, extractGmailMailboxAccount } = require('../commands/integrations');
|
|
2817
|
+
const account = extractGmailMailboxAccount(raw);
|
|
2818
|
+
// Account --account <id> is a selector, not the workspace opt-in.
|
|
2819
|
+
// Scratch folders refuse every slack verb the same way as gmail/inbox.
|
|
2820
|
+
const gate = requireAccountBound(account.args.filter((arg) => arg !== '--account'));
|
|
2821
|
+
if (!gate.ok) {
|
|
2822
|
+
process.exit(refuseAccountGlobal());
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2781
2825
|
const subcommand = gate.args[0];
|
|
2782
2826
|
const args = gate.args.slice(1);
|
|
2783
2827
|
slackCommand(subcommand, ...args)
|