atris 3.58.6 → 3.58.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/GETTING_STARTED.md +2 -2
  2. package/PERSONA.md +11 -11
  3. package/README.md +9 -1
  4. package/atris/GEMINI.md +7 -6
  5. package/atris/PERSONA.md +4 -4
  6. package/atris/features/README.md +77 -6
  7. package/atris/policies/engineering-principles.md +129 -0
  8. package/atris/policies/genesis.md +112 -0
  9. package/atris/policies/product-design-principles.md +100 -0
  10. package/atris/skills/README.md +44 -15
  11. package/atris/skills/aeo/SKILL.md +10 -10
  12. package/atris/skills/atris/SKILL.md +1 -1
  13. package/atris/skills/design/SKILL.md +3 -1
  14. package/atris/skills/engines/SKILL.md +42 -50
  15. package/atris/skills/meta/SKILL.md +4 -4
  16. package/atris/skills/youtube/SKILL.md +11 -11
  17. package/bin/atris.js +60 -8
  18. package/commands/aeo.js +9 -12
  19. package/commands/analytics.js +8 -11
  20. package/commands/auth.js +8 -2
  21. package/commands/autopilot.js +4 -3
  22. package/commands/avail.js +1 -1
  23. package/commands/brain.js +4 -1
  24. package/commands/business.js +13 -8
  25. package/commands/close.js +2 -1
  26. package/commands/computer.js +15 -10
  27. package/commands/context-sync.js +3 -3
  28. package/commands/design.js +362 -0
  29. package/commands/doc-health.js +377 -0
  30. package/commands/drive.js +32 -0
  31. package/commands/experiments.js +13 -4
  32. package/commands/improve.js +68 -2
  33. package/commands/integrations.js +2 -5
  34. package/commands/land.js +144 -4
  35. package/commands/learn.js +7 -2
  36. package/commands/member.js +239 -58
  37. package/commands/mission.js +94 -18
  38. package/commands/pack.js +2 -2
  39. package/commands/probe.js +11 -5
  40. package/commands/pull.js +1 -1
  41. package/commands/pulse.js +38 -0
  42. package/commands/push.js +1 -1
  43. package/commands/rainmaker.js +3 -16
  44. package/commands/rsi.js +156 -0
  45. package/commands/spaceship.js +1 -1
  46. package/commands/stream.js +27 -2
  47. package/commands/study.js +15 -9
  48. package/commands/sync.js +1 -1
  49. package/commands/task.js +54 -3
  50. package/commands/workflow.js +17 -7
  51. package/commands/youtube.js +76 -8
  52. package/lib/apply-gate.js +22 -4
  53. package/lib/codex-flight.js +28 -5
  54. package/lib/daily-log.js +88 -0
  55. package/lib/design-api.js +130 -0
  56. package/lib/engine-ask.js +1 -1
  57. package/lib/first-minute.js +1 -6
  58. package/lib/fleet.js +4 -1
  59. package/lib/improve-vitals-html.js +3 -2
  60. package/lib/known-commands.js +3 -3
  61. package/lib/lesson-contradiction.js +2 -2
  62. package/lib/map-refs.js +183 -0
  63. package/lib/member-context.js +42 -0
  64. package/lib/mission-room.js +4 -4
  65. package/lib/noninteractive.js +15 -4
  66. package/lib/policy-lessons.js +1 -1
  67. package/lib/receipt-block.js +137 -28
  68. package/lib/rsi-record.js +335 -0
  69. package/lib/runner-command.js +1 -1
  70. package/lib/scorecard.js +4 -4
  71. package/lib/sleep-sync.js +11 -0
  72. package/lib/state-detection.js +36 -17
  73. package/lib/task-db.js +74 -53
  74. package/lib/task-list-keeper.js +192 -0
  75. package/lib/todo-fallback.js +10 -4
  76. package/lib/todo.js +22 -10
  77. package/lib/wish-delegate.js +19 -5
  78. package/mcp/atris-mcp/index.mjs +227 -0
  79. package/package.json +4 -2
  80. package/scripts/det/det.js +2 -2
  81. package/scripts/det/pr-description.js +2 -2
  82. package/scripts/det/test.js +2 -2
  83. package/scripts/det/ytnotes +43 -8
  84. package/utils/api.js +1 -1
  85. package/utils/auth.js +79 -14
  86. package/utils/backend-root.js +31 -0
  87. package/utils/config.js +5 -4
  88. package/utils/owner-identity.js +61 -0
  89. package/atris/policies/LESSONS.md +0 -13
  90. package/atris/skills/autopilot/atris-autopilot.md +0 -71
@@ -6,8 +6,8 @@ Agent-agnostic skills. Works with Claude, Cursor, Codex, any LLM agent.
6
6
 
7
7
  Every process = **Skill + Policy**
8
8
 
9
- - `skills/[name]/SKILL.md` — How to DO (process)
10
- - `policies/[name].md` — How to REVIEW (validation)
9
+ - `skills/[name]/SKILL.md`: How to DO (process)
10
+ - `policies/[name].md`: How to REVIEW (validation)
11
11
 
12
12
  ## Integration
13
13
 
@@ -25,19 +25,46 @@ cp -r atris/skills/[name] ~/.codex/skills/
25
25
 
26
26
  | Skill | Description | Policy |
27
27
  |-------|-------------|--------|
28
- | atris | Workflow enforcement + plan/do/review | `policies/ANTISLOP.md` |
29
- | autopilot | PRD-driven autonomous execution | — |
30
- | autoresearch | Bounded keep/revert experiment loops via `atris/experiments/` | — |
31
- | backend | Backend architecture anti-patterns | `policies/atris-backend.md` |
28
+ | aeo | Content engineered to get cited by ChatGPT, Claude, and Gemini | - |
29
+ | apps | View, manage, and trigger Atris apps | - |
30
+ | atris | Workspace navigation, tasks, MAP.md, where-is-X questions | `policies/ANTISLOP.md` |
31
+ | atris-feedback | Submit, list, resolve, close, or delete customer feedback | - |
32
+ | autopilot | Run one autonomous plan/do/review tick | - |
33
+ | autoresearch | Keep/revert experiment loop for experiment packs | - |
34
+ | backend | Backend architecture policy | `policies/atris-backend.md` |
35
+ | blocks | Author Atris block documents: docs, decks, reports | - |
36
+ | calendar | Google Calendar via AtrisOS API | - |
37
+ | copy-editor | Detects and fixes AI writing patterns | - |
38
+ | create-app | Build and deploy an Atris app from a description | - |
39
+ | create-member | Create and manage MEMBER.md team members | - |
32
40
  | design | Frontend aesthetics policy | `policies/atris-design.md` |
33
- | calendar | Google Calendar integration via AtrisOS | — |
34
- | drive | Google Drive + Sheets integration via AtrisOS | — |
35
- | email-agent | Gmail integration via AtrisOS | — |
36
- | memory | Context and memory management | — |
37
- | meta | Metacognition for agents | `policies/LESSONS.md` |
41
+ | drive | Google Drive, Docs, and Sheets via AtrisOS API | - |
42
+ | email-agent | Gmail via AtrisOS API | - |
43
+ | endgame | Pick the next horizon and write the reverse path as tasks | - |
44
+ | engines | Dispatch work to an installed terminal agent or engine profile | - |
45
+ | fable-method | Working method for daily-driver models | - |
46
+ | flow | All-day operating partner: identity, goals, live status | - |
47
+ | github | GitHub via AtrisOS API | - |
48
+ | imessage | Inspect and send local macOS iMessage | - |
49
+ | improve | One verified, scored improvement tick with a receipt | - |
50
+ | launch | Write a release post for Twitter and LinkedIn | - |
51
+ | loop | Schedule the recurring autopilot heartbeat | - |
52
+ | magic-inbox | Autonomous inbox triage, drafts, and archive | - |
53
+ | memory | Search and reason over journal history | - |
54
+ | meta | Metacognition for agents | `atris/lessons.md` |
55
+ | notion | Notion via AtrisOS API | - |
56
+ | ramp | Ramp card and spend management | - |
57
+ | render-cli | Render.com CLI inspect, auth, and deploys | - |
58
+ | research-search | Research sweep across arxiv, semantic scholar, github, web | - |
59
+ | skill-improver | Audit and improve skills against the Anthropic guide | - |
60
+ | slack | Slack via AtrisOS API | - |
61
+ | slides | Google Slides via AtrisOS API | - |
62
+ | tidy | Workspace maintenance: stale docs, broken refs, abandoned tasks | - |
63
+ | wake | Wake a member and run one closed-loop tick | - |
64
+ | wiki | Local-first project wiki: ingest, query, lint | - |
38
65
  | writing | Essay process with gates | `policies/writing.md` |
39
- | copy-editor | Detects and fixes AI writing patterns | - |
40
- | skill-improver | Audit and improve skills against Anthropic guide | — |
66
+ | x-search | X/Twitter search via xAI Grok API | - |
67
+ | youtube | YouTube discovery, notes, and learning | - |
41
68
 
42
69
  ## ClawHub (External Distribution)
43
70
 
@@ -45,8 +72,10 @@ Skills we publish to OpenClaw's ClawHub marketplace. These have YAML frontmatter
45
72
 
46
73
  | Skill | Description | Status |
47
74
  |-------|-------------|--------|
48
- | clawhub/atris | Codebase intelligence — MAP.md navigation for any agent | Ready to publish |
49
- | clawhub/philosophy-of-work | Agent onboarding — philosophy, 60s start, proof contract | Ready to publish |
75
+ | clawhub/atris | Codebase intelligence: MAP.md navigation for any agent | Ready to publish |
76
+ | clawhub/chief-of-staff | Daily briefing agent that learns your patterns | Ready to publish |
77
+ | clawhub/member-runtime | Load and run MEMBER.md team members | Ready to publish |
78
+ | clawhub/philosophy-of-work | Agent onboarding: philosophy, 60s start, proof contract | Ready to publish |
50
79
 
51
80
  ```bash
52
81
  # Publish to ClawHub
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: aeo
3
- description: "AI Engine Optimization — write content engineered to get cited by ChatGPT, Claude, and Gemini. Not SEO. Triggers on: aeo, AI engine, llm citation, get cited, write for ai."
3
+ description: "AI Engine Optimization: write content engineered to get cited by ChatGPT, Claude, and Gemini. Not SEO. Triggers on: aeo, AI engine, llm citation, get cited, write for ai."
4
4
  when_to_use: "Use when the user wants content that ranks in AI answers (not Google SERP). Examples: 'write an AEO page', 'get ExampleCo cited by ChatGPT', 'aeo for our pricing page', 'make this quotable by LLMs'."
5
5
  version: 0.1.0
6
6
  allowed-tools: Read, Write, Edit, Glob, Grep, Bash
@@ -10,7 +10,7 @@ tags:
10
10
  - marketing
11
11
  ---
12
12
 
13
- # AEO — AI Engine Optimization
13
+ # AEO: AI Engine Optimization
14
14
 
15
15
  Write content that LLMs cite when a human asks them a question. Different objective than SEO, different rules than craft writing.
16
16
 
@@ -48,7 +48,7 @@ Entity graph lives in the **customer's EC2 workspace** (not agent_files, not DB)
48
48
  1. **Front-load the claim.** LLMs quote sentence 1 of a paragraph. No throat-clearing.
49
49
  2. **Name entities explicitly.** "ExampleCo" not "a leading freight platform." Entity density is how LLMs disambiguate and cite.
50
50
  3. **Canonical definition.** One sentence owns `X is Y that does Z` for the category. Make it liftable.
51
- 4. **Q&A scaffolding.** H2s in question form: "What is X?" "How does X work?" — matches the prompts LLMs actually get.
51
+ 4. **Q&A scaffolding.** H2s in question form: "What is X?" "How does X work?", matching the prompts LLMs actually get.
52
52
  5. **Declarative stats with sources.** "$2.3B market (McKinsey 2025)" beats "a growing market." Citable atoms.
53
53
  6. **Comparison tables.** LLMs love structured data. Build one per category claim.
54
54
  7. **Fresh dates visible.** "Updated 2026-04-17" at top. LLMs weight recency.
@@ -62,11 +62,11 @@ Entity graph lives in the **customer's EC2 workspace** (not agent_files, not DB)
62
62
  READ entity graph → DRAFT → SELF-SCORE → WRITE to workspace → (phase 2: AUDIT)
63
63
  ```
64
64
 
65
- 1. **READ** — Pull `entities.md`, `definitions.md`, `stats.md` from customer workspace. If missing, create skeleton files first.
66
- 2. **DRAFT** — Generate article applying all 10 rules. Topic + target queries + entity context → article.
67
- 3. **SELF-SCORE** — Append a `## AEO Self-Check` section: each rule scored pass/fail with evidence.
68
- 4. **WRITE** — Save to `/workspace/atris/aeo/drafts/<slug>.md`.
69
- 5. **AUDIT** (phase 2) — Run target queries against 4 LLMs, measure whether article is cited, write results to `/workspace/atris/aeo/audits/<slug>-<date>.md`.
65
+ 1. **READ**: Pull `entities.md`, `definitions.md`, `stats.md` from customer workspace. If missing, create skeleton files first.
66
+ 2. **DRAFT**: Generate article applying all 10 rules. Topic + target queries + entity context → article.
67
+ 3. **SELF-SCORE**: Append a `## AEO Self-Check` section: each rule scored pass/fail with evidence.
68
+ 4. **WRITE**: Save to `/workspace/atris/aeo/drafts/<slug>.md`.
69
+ 5. **AUDIT** (phase 2): Run target queries against 4 LLMs, measure whether article is cited, write results to `/workspace/atris/aeo/audits/<slug>-<date>.md`.
70
70
 
71
71
  ## Entity graph layout (in customer workspace)
72
72
 
@@ -90,7 +90,7 @@ atris write aeo "<topic>" --workspace <name>
90
90
  atris aeo init --workspace <name>
91
91
 
92
92
  # View current drafts
93
- atris ls workspace/atris/aeo/drafts --workspace <name>
93
+ ls workspace/atris/aeo/drafts
94
94
  ```
95
95
 
96
96
  ## Credits
@@ -107,7 +107,7 @@ atris ls workspace/atris/aeo/drafts --workspace <name>
107
107
  - Self-score section is mandatory in every draft.
108
108
  - Never hedge in the body. Hedging kills citation rate.
109
109
  - Never fabricate stats. If a stat is uncited, flag it in self-check.
110
- - Entity graph skeleton auto-creates if missing — never fail on first run.
110
+ - Entity graph skeleton auto-creates if missing. Never fail on first run.
111
111
 
112
112
  ## Related
113
113
 
@@ -29,7 +29,7 @@ Commands: plan → do → review
29
29
 
30
30
  Key behaviors:
31
31
  - Mission-shaped intent wins: run `atris mission run ...` before normal task selection when the user invokes it or asks for a loop.
32
- - Read PERSONA.md (3-4 sentences, ASCII visuals)
32
+ - Read PERSONA.md (MAP.md first, plain words, lead with the outcome)
33
33
  - Check MAP.md for file:line refs
34
34
  - Use `atris task` for claims, proof, ready, and accept
35
35
  - Give every task a plain first layer: what changes, why it matters, and what
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: design
3
3
  description: Frontend aesthetics policy. Use when building UI, components, landing pages, dashboards, or any frontend work. Prevents generic ai-generated look.
4
- version: 3.2.16
4
+ version: 3.2.18
5
5
  allowed-tools: Read, Write, Edit, Bash, Glob
6
6
  tags:
7
7
  - design
@@ -136,6 +136,8 @@ Every entry: id, rule, detector, status. A detector is a regex/command a gate ca
136
136
  | D31 | developer-only overlays stay off the product surface by default; any temporary visible launcher must have an immediate dismiss control | judgment | active |
137
137
  | D32 | before changing repeated UI copy, verify the operator's exact executable and surface; matching labels do not prove the installed app, dev app, header, and composer share one live path | judgment | active |
138
138
 
139
+ | D34 | engine settings show only the selected engine’s effective model and supported controls; preserve saved choices missing from the option list instead of displaying another engine | `node scripts/test-engine-settings.mjs` in project-obelisk | graduated (engine settings regression) |
140
+
139
141
  Measured recipes live in the mimic studies: `~/arena/mimic-beautiful-ui/LESSONS.md` (18 AI-interface components with exact tokens) and its `remix.css` :root block (the portable Atris token sheet, coffee + paper themes). Start there before designing an agent surface.
140
142
 
141
143
  ## Self-Improve (part of the job)
@@ -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, Antigravity (agy), and opencode. Triggers on: use codex, use cursor, use devin, use grok, use agy, use antigravity, use gemini, gemini session, use fable, use claude, use opencode, use atris, engine, dispatch to, worker agent, second opinion build."
4
- version: 1.5.1
4
+ version: 1.7.0
5
5
  tags:
6
6
  - engines
7
7
  - claude
@@ -20,7 +20,7 @@ tags:
20
20
  - orchestration
21
21
  ---
22
22
 
23
- # Engines — interchangeable terminal workers
23
+ # Engines: interchangeable terminal workers
24
24
 
25
25
  One contract, eleven live profiles. The orchestrator writes a bounded task prompt, dispatches it to an engine, then **independently verifies, lands, and pushes** the result. Engines never self-certify.
26
26
 
@@ -59,54 +59,46 @@ substitute raw Claude or another engine and call the result FABLE.
59
59
 
60
60
  Raw spawns are not the default because they skip Atris receipts, watch, and coaching.
61
61
 
62
- | Engine | Command | Notes |
63
- |--------|---------|-------|
64
- | Atris Fast | `atris chat --print "<prompt>"` (equivalently `ax --fast --print`) | Local tool runtime over the api.atris.ai fast lane. Best for bounded lookups and small verified edits. |
65
- | Claude | `claude -p "<prompt>"` | Uses the local Claude configuration. Add `--model opus` for maximum-depth review or `--model sonnet` for speed. |
66
- | 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) |
67
- | Cursor | `cursor-agent --trust -p "<prompt>"` (run from the target repo) | Headless print mode; `--trust` required for non-interactive |
68
- | Fable | `atris engine fable "<question>"` | Canonical read-only FABLE ask with guards, live log, receipt, and health tracking. Scale `--timeout` to the work when needed. |
69
- | Composer | `atris run "<objective>" --engine composer` | Fast navigator/executor profile routed through the installed `ax` binary. |
70
- | Haiku | `claude -p "<prompt>" --model claude-haiku-4-5` | Fast validation and bounded read-only checks. |
71
- | 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` |
72
- | Grok | `grok --always-approve -p "<prompt>"` (run from the target repo) | Headless single-turn via `-p`; default model grok-4.6. Very fast on lookups (~5-10s, reads MAP first). Great for quick second opinions; use `--best-of-n <N>` for tricky bounded builds. Uses grok.com login |
73
- | Antigravity | `agy --mode accept-edits --add-dir "$PWD" -p "<prompt>"` (run from the target repo) | `agy` executor profile; also answers to "gemini". **`--add-dir` is mandatory for writes** — without it agy edits its own scratch folder (`~/.gemini/antigravity-cli/scratch/`) and the project never changes, which looks like a silent failure (verified live 2026-08-28). Use `--mode plan --sandbox` for read-only review, `--model <id>` to pin a model, and `--dangerously-skip-permissions` if a build still stalls on an approval prompt. |
74
- | opencode | `opencode run "<prompt>"` (read-only ask: `opencode run --agent plan "<prompt>"`) | Headless print mode; exits when done. Pin a model with `-m provider/model`. Build work needs `--auto` to auto-approve permissions (dangerous: run in an isolated worktree). Verified live 2026-08-21, ~7s per plan-mode lookup. |
62
+ Smoke: `reply with the word OK`, run from `$HOME`, 120s cap, one at a time on a loaded Mac (2026-09-23). Seconds are wall time under that load.
63
+
64
+ | Engine | Exact command | Pinned model | Verified | Seconds | Notes |
65
+ |--------|---------------|--------------|----------|--------:|-------|
66
+ | Atris Fast | `atris chat --print "<prompt>"` | `atris:fast` | 2026-09-23 | 3.2 | Needs an initialized `atris/` workspace; see runtime requirements below. |
67
+ | Claude | `claude -p "<prompt>" --model claude-opus-5-5 --output-format json --no-session-persistence` | `claude-opus-5-5` | 2026-09-23 | 20.3 | `--model opus` also resolves to `claude-opus-5-5` today; pin the id for reproducibility. |
68
+ | Codex | `codex exec --dangerously-bypass-approvals-and-sandbox --ephemeral -m gpt-6-sol -c model_reasoning_effort=high -o <result-file> "<prompt>" </dev/null` (run from the target repo/worktree; read-only: swap the bypass flag for `--sandbox read-only`) | `gpt-6-sol`, high | 2026-09-23 | 13.8 | Keep the `</dev/null`: with stdin open codex prints "Reading additional input from stdin..." and waits forever (observed 2026-09-23). Outside a git repo add `--skip-git-repo-check` or it exits 1 (re-checked 2026-09-23). Final answer lands in the `-o` file. Run as a tracked background Bash task; in one-shot `claude -p` workers run it in the FOREGROUND, a one-shot session never wakes again (2026-08-11). `codex-companion.mjs task --background` is deprecated: its job store never notifies the session (2026-08-10). |
69
+ | Cursor | `cursor-agent --trust --model composer-2.5 -p "<prompt>"` (run from the target repo) | `composer-2.5` | 2026-09-23 | 37.5 | `--trust` required for non-interactive. |
70
+ | Fable | `atris engine fable --timeout 120 --json "<question>"` | `claude-fable-5` | 2026-09-23 | 21.4 | Canonical read-only FABLE ask with receipt; scale `--timeout` to the work. |
71
+ | Composer | `cursor-agent --trust --model composer-2.5 -p "<prompt>"` | `composer-2.5` via Cursor | 2026-09-23 | 37.5 | Same binary as Cursor. |
72
+ | Haiku | `claude -p "<prompt>" --model claude-haiku-4-5 --output-format json --no-session-persistence` | `claude-haiku-4-5` | 2026-09-23 | 19.0 | Fast validation and bounded read-only checks. |
73
+ | Devin (build) | `devin -p --permission-mode dangerous --model swe-2-max --prompt-file <brief>` (run from an isolated worktree) | `swe-2-max` (Free tag in `devin models list`, 2026-09-23) | 2026-09-23 | 14.0 | In `-p` mode the default permission mode rejects shell commands too, so even a read-only audit dies after one step (2026-09-23). Keep the brief outside the worktree. Long runs (5+ min) can print nothing even on success: judge by the worktree diff. `devin cloud` outlives this machine. |
74
+ | Devin (search) | `devin -p --permission-mode dangerous --model swe-1.7-lightning -- "<prompt>"` | `swe-1.7-lightning` (paid, no Free tag on 2026-09-23) | 2026-09-23 | 13.9 | |
75
+ | Grok | `grok --always-approve --model grok-4.7 -p "<prompt>"` (run from the target repo) | `grok-4.7` | 2026-09-23 | 11.7 | Unpinned default is now `grok-4.7-build-fast`; `grok models` lists the menu. Uses grok.com login. `--best-of-n <N>` for tricky bounded builds. |
76
+ | Antigravity (agy) | `agy --mode accept-edits --add-dir "$PWD" --model gemini-3.8-flash-high --output-format json -p "<prompt>"` (run from the target repo) | `gemini-3.8-flash-high` | 2026-09-23 | 15.9 | **`--add-dir` is mandatory for writes**: without it agy edits `~/.gemini/antigravity-cli/scratch/` and the project never changes (2026-08-28). `--mode plan --sandbox` for read-only review. Also answers to "gemini". |
77
+ | opencode | `opencode run -m opencode/muse-spark-1.3-contributor-free "<prompt>"` (read-only: add `--agent plan`) | `opencode/muse-spark-1.3-contributor-free` | 2026-09-23 | 41.1 | Build work needs `--auto` (isolated worktree only). `opencode models` lists the live menu. |
75
78
 
76
79
  Headless dispatch permissions (verified 2026-08-11): `codex exec`, `grok`, and `cursor-agent` are allowlisted in `~/.claude/settings.json` so fresh and one-shot sessions can dispatch without a human approval click. A cold session that gets "requires approval" on an engine command means that allowlist regressed.
77
80
 
78
81
  ## Picking an engine
79
82
 
80
- - **Atris Fast** — cheap bounded lookups, single-file facts, small verified edits, and high-volume fan-out.
81
- - **FABLE** — strongest judgment lane. Use the canonical Atris profile for deep review, synthesis, validation, and complex builds.
82
- - **Claude** — direct Claude profile when the operator names Claude rather than FABLE.
83
- - **Codex** — deep root-cause work, long autonomous builds, second-opinion diagnosis. Slowest; runs sandboxed.
84
- - **Cursor** — fast bounded edits and refactors in a single repo.
85
- - **Composer / Haiku** — fast, bounded navigation, edits, and validation where a max-tier model would be wasteful.
86
- - **Devin** — multi-step feature work; use `cloud` when the run should survive laptop sleep.
87
- - **Grok** - fastest frontier lookups and quick second opinions (grok-4.6, ~5-10s; reads MAP first); use `--best-of-n` for tricky bounded builds. Uses grok.com login.
88
- - **Antigravity / agy** — flexible executor work across Gemini, Claude, and GPT-OSS models; use `agy` as the canonical short name.
89
- - **opencode** — multi-provider executor in one CLI (Claude, GPT, Gemini, DeepSeek menus via `opencode models`); plan agent for read-only asks, `--auto` builds only inside an isolated worktree.
83
+ - **Multi-file or long build**: Devin `swe-2-max` while its Free tag holds (check `devin models list`); Codex `gpt-6-sol` if the tag is gone.
84
+ - **Judgment-heavy build**: Opus 5.5 subagent (Claude row).
85
+ - **Review / deep judgment**: FABLE profile; Codex `gpt-6-sol` or Opus 5.5 as second validator.
86
+ - **Quick fix**: Cursor.
87
+ - **Search / bounded lookup**: Atris Fast; Haiku or Devin `swe-1.7-lightning` for read-only sweeps; Grok for quick second opinions.
88
+ - **agy / opencode**: extra executors when you want a different model family.
90
89
  - Parallel builds across repos: one engine job per repo, never two engines writing the same checkout.
91
90
 
92
- ## Models worth pinning (verified live 2026-08-15)
91
+ ## Models worth pinning (verified live 2026-09-23)
93
92
 
94
- Each engine CLI can pin a specific model. Current best picks:
93
+ | Engine | Flag | Alternates on the live menu |
94
+ |--------|------|-----------------------------|
95
+ | Claude | `--model <id>` | `claude-opus-5-5`, `claude-haiku-4-5` |
96
+ | Devin | `--model <id>` | `swe-2-max`, `swe-2-high`, `swe-2-medium` (Free); `claude-opus-5-5-high`, `gpt-6-sol` (paid) |
97
+ | Cursor | `--model <id>` | `composer-2.5`, `grok-4.7-xhigh`, `claude-opus-5-thinking-high`; `--list-models` |
98
+ | Grok | `--model <id>` | `grok-4.7`, `grok-4.7-build-fast` (default), `grok-4.6`, `grok-4.5`; `grok models` |
99
+ | Codex | `-m <id>` | `gpt-6-sol` is the `~/.codex/config.toml` default |
95
100
 
96
- | Engine | Flag | Best models today |
97
- |--------|------|-------------------|
98
- | Claude / Fable | `--model opus` | `opus` currently resolves to Opus 5; use the explicit Opus 4.8 identifier only for reproducibility |
99
- | 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 |
100
- | 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 |
101
- | Composer | `--engine composer` | `composer 2.5` through the Atris profile |
102
- | Haiku | `--model claude-haiku-4-5` | `haiku` for fast validation |
103
- | Grok | (default) | `grok-4.6` default (confirmed live 2026-08-12, ~5s lookup), `grok-4.5` still available via `-m` |
104
- | Codex | `-m <model>` | CLI default rides `~/.codex/config.toml`; pin with `-m` only when the task needs it |
105
- | Antigravity / agy | `--model <id>` | `gemini-3.7-flash-high` for speed, `gemini-3.1-pro-high` for depth, `claude-sonnet-4-6`, `claude-opus-4-6-thinking`, or `gpt-oss-120b-medium` |
106
- | opencode | `-m <provider/model>` | `opencode/big-pickle`, `opencode/gpt-5.2`, `opencode/claude-opus-4-8`; `opencode models` lists the live menu |
107
- | Atris Fast | (fixed) | api.atris.ai fast lane |
108
-
109
- Re-verify this table when a lab ships a new model: run each CLI's model-list command, smoke one lookup, and update the row. Free-tier windows (like swe-1.7 now) are the moment to fan out volume work.
101
+ Pins expire 30 days after their verified date. Re-verify on a new model: run the CLI's model list, smoke one prompt, update the row.
110
102
 
111
103
  ## Keep the local roster current
112
104
 
@@ -115,7 +107,7 @@ Run `atris engine doctor`, then `atris engine --help`. The canonical profiles li
115
107
  ## Atris Fast runtime requirements (verified live 2026-07-03)
116
108
 
117
109
  - Must run from an **initialized Atris workspace** (an `atris/` folder) under an allowed workspace root (e.g. `~/arena/*`). `atris chat --print` outside one exits 1 with "Run atris init"; `ax --fast --print` outside an allowed root fail-closes with `{ok:false, error:"workspace_path must be under an allowed local workspace root"}`.
118
- - In an allowed root **without** an `atris/` folder the turn silently routes to the cloud no-tools chat lane — the model will honestly refuse file work ("no Atris Desktop runtime attached"). If the output says that, you dispatched from the wrong directory; it is not an engine failure.
110
+ - In an allowed root **without** an `atris/` folder the turn silently routes to the cloud no-tools chat lane. The model will honestly refuse file work ("no Atris Desktop runtime attached"). If the output says that, you dispatched from the wrong directory; it is not an engine failure.
119
111
 
120
112
  ## Prompt contract (every dispatch)
121
113
 
@@ -140,16 +132,16 @@ the actual final state: draft, queued, and merged are different outcomes.
140
132
  Record elapsed time, engine calls, retries, and exposed token usage. Unknown
141
133
  usage stays unknown; one pilot does not establish a speedup or perfect accuracy.
142
134
 
143
- 1. Name the absolute repo path and tell the engine to `cd` there (Atris Fast scopes to the cwd it runs from — cd first, and name absolute paths in the prompt).
135
+ 1. Name the absolute repo path and tell the engine to `cd` there (Atris Fast scopes to the cwd it runs from, so cd first and name absolute paths in the prompt).
144
136
  2. Bound the slice: one task, explicit exit criteria, the verify command to run.
145
- 3. Git rules: `git status` first; stage only own files; never revert others' changes; never destructive git; work on a branch `member/<name>-<slug>` or a worktree. (Atris Fast does not run git — for edit tasks the orchestrator commits after verifying.)
146
- 4. Require a final report: files changed, verify command + result, branch name. (Atris Fast returns one JSON `output` field — ask for file:line evidence in it.)
137
+ 3. Git rules: `git status` first; stage only own files; never revert others' changes; never destructive git; work on a branch `member/<name>-<slug>` or a worktree. (Atris Fast does not run git. For edit tasks the orchestrator commits after verifying.)
138
+ 4. Require a final report: files changed, verify command + result, branch name. (Atris Fast returns one JSON `output` field. Ask for file:line evidence in it.)
147
139
 
148
- ## Landing (orchestrator duties — never skip)
140
+ ## Landing (orchestrator duties, never skip)
149
141
 
150
142
  - **Codex sandbox cannot reach github.com and may get read-only repo access.** Expect temp clones / `git format-patch` fallbacks under `/private/tmp`. Apply patches in a fresh worktree, re-run the verify command yourself, then push.
151
- - Cursor and Devin run unsandboxed — still re-run the verify command yourself before pushing.
152
- - Long Devin runs (5+ min) can return empty stdout even when the build fully succeeded — judge by `git status` and the diff in its worktree, never by the printed report.
153
- - Atris Fast answers are model output over a real tool runtime — treat `output` as a claim, spot-check the cited file:line, and re-run any verifier yourself before acting on it.
143
+ - Cursor and Devin run unsandboxed. Still re-run the verify command yourself before pushing.
144
+ - Long Devin runs (5+ min) can return empty stdout even when the build fully succeeded. Judge by `git status` and the diff in its worktree, never by the printed report.
145
+ - Atris Fast answers are model output over a real tool runtime. Treat `output` as a claim, spot-check the cited file:line, and re-run any verifier yourself before acting on it.
154
146
  - Engine task DBs and receipts written inside a sandbox are snapshots; reconcile against the live `atris task` plane after landing.
155
- - A stalled job (no log output for 30+ min) gets cancelled and taken over; don't wait on it. Atris Fast turns that exceed ~60s have hung — kill and retry once with a tighter prompt.
147
+ - A stalled job (no log output for 30+ min) gets cancelled and taken over; don't wait on it. Atris Fast turns that exceed ~60s have hung. Kill and retry once with a tighter prompt.
@@ -23,7 +23,7 @@ How to be an effective agent. Load this when you need to check yourself.
23
23
 
24
24
  1. **MAP first** - Read `atris/MAP.md` before any search. It's the index.
25
25
  2. **Journal context** - Check today's log for recent work, patterns, blockers.
26
- 3. **LESSONS.md** - What failed before? Don't repeat.
26
+ 3. **atris/lessons.md** - What failed before? Don't repeat.
27
27
  4. **Skill routing** - Frontend? Load `design`. Backend? Load `backend`. Writing? Load `writing`.
28
28
 
29
29
  ## Pace control
@@ -48,7 +48,7 @@ Stop and reassess when:
48
48
  ## Memory leverage
49
49
 
50
50
  Before acting:
51
- 1. Check `atris/policies/LESSONS.md` - short lessons from past mistakes
51
+ 1. Check `atris/lessons.md` - short lessons from past mistakes
52
52
  2. Check `atris/features/` - prior art for similar work
53
53
  3. Check journal history - `grep -i "<keyword>" atris/logs/**/*.md`
54
54
 
@@ -72,7 +72,7 @@ Act (execute with focus)
72
72
  ↓
73
73
  Check (output match intent?)
74
74
  ↓
75
- Learn (add to LESSONS if miss)
75
+ Learn (add to lessons.md if miss)
76
76
  ```
77
77
 
78
78
  ## Anti-patterns
@@ -88,7 +88,7 @@ Learn (add to LESSONS if miss)
88
88
  ## Skill evolution
89
89
 
90
90
  Skills improve from your mistakes:
91
- 1. After REVIEW, log learnings to `LESSONS.md` (format: `date | skill | lesson`)
91
+ 1. After REVIEW, log learnings to `atris/lessons.md` (one line per lesson)
92
92
  2. Repeated lessons (2-3x) get promoted into the relevant skill
93
93
  3. Next agent loads the improved skill
94
94
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: youtube
3
3
  description: "YouTube discovery and learning. Get watch permalinks with atris youtube search QUERY (free, local ytsearch/yt-dlp). On 429 use printed rows if any; else the CLI retries once, then 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.18.18
4
+ version: 2.18.23
5
5
  tags:
6
6
  - youtube
7
7
  - research
@@ -22,7 +22,7 @@ search QUERY (free)
22
22
  --> thin: check: fill this, then next: atris youtube teach <first-url>
23
23
  --> --json stays quiet
24
24
  |
25
- 429 --> printed rows? use them (no retry)
25
+ 429 --> printed rows? use them (no retry). warning/NA/None print lines are not rows
26
26
  --> else CLI retries once
27
27
  --> cached rows printed? use them (same rich mint or thin check as live rows)
28
28
  --> rate-limit sentence printed? STOP
@@ -34,14 +34,14 @@ search QUERY (free)
34
34
  | then next: atris youtube teach <same-url>
35
35
  | --json stays quiet
36
36
  | --save files brief + pack-named apply when notes have a number or named mechanism; a multi-url --save batch proves the first saved pack the same way single-url --save does; thin --save refuses
37
- | playlist expand keeps printed yt-dlp rows on 429
38
- | notes keep a written yt_<id>.md (and ytnotes keeps a written manual or auto en / en-orig / en-US / en-GB VTT) when yt-dlp exits 429 or a later error, or --print is empty
37
+ | playlist expand keeps printed yt-dlp rows on 429 and skips warning lines so they do not become fake ids; expander passes --no-warnings like watch fetch
38
+ | notes keep a written yt_<id>.md (and ytnotes keeps a written manual or auto en / en-orig / en-US / en-GB VTT) when yt-dlp exits 429 or a later error, or --print is empty; a leaked warning line or NA/None print is not the video id
39
39
  | watch, youtu.be, shorts, embed, live, /e/, and youtube-nocookie embed urls all resolve the same video id for that keep
40
40
  | a copied #t= timestamp still finds yt_<id>.en.vtt
41
41
  | a watch?v=&list= copy still finds yt_<video>.en.vtt when -J dumps playlist JSON
42
42
  | or teach URL [--section N] (one chapter: claim numbers, named mechanisms, one check; free unless --save)
43
- | printed yt-dlp metadata is a hit even on 429
44
- | a written VTT or clean.txt is used when the caption URL fetch fails, `-J` stdout is empty, or `-J` dumps a playlist for a watch?v=&list= URL
43
+ | printed yt-dlp metadata is a hit even on 429; a leaked WARNING/ERROR/INFO line before the -J dump is skipped so the json still parses
44
+ | a written VTT or leftover same-id clean.txt is used when the caption URL fetch fails, `-J` stdout is empty, or `-J` dumps a playlist; leftover [mm:ss] stamps become cues; another video leftover is not invent-keep
45
45
  | a taught section that is not last prints next: recap TEXT or skip
46
46
  | last section: rich ephemeral apply, failing check, and score 0, then next: atris youtube watch tick; save pack keep stays; no recap next
47
47
  | next --section refuses until recap/skip
@@ -79,9 +79,9 @@ never paste tokens, never /auth/cli
79
79
  ```
80
80
 
81
81
  1. Get watch permalinks: `atris youtube search QUERY` (free). A rich hit mints `atris/experiments/search-<query>/`, writes one pack-named Apply, and prints `score: 0` only when that Apply starts failing. A thin hit prints `check: fill this`, then one next teach command. `--json` stays quiet and writes no pack.
82
- 2. If 429: use any rows already printed. If none, wait/retry is already in the CLI. If it prints cached rows, use those. Cached rows mint or print the same rich or thin gate as a live hit. If it prints `youtube rate-limited local search. do not use --paid as a fallback; retry later.`, STOP. Do not run `--paid`.
82
+ 2. If 429: use any rows already printed. A leaked warning line or a `youtu.be/NA` / `youtu.be/None` row is not printed. If none, wait/retry is already in the CLI. If it prints cached rows, use those. Cached rows mint or print the same rich or thin gate as a live hit. If it prints `youtube rate-limited local search. do not use --paid as a fallback; retry later.`, STOP. Do not run `--paid`.
83
83
  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.
84
- 4. `atris youtube notes URL` after a URL is picked (free). Notes is ephemeral unless `--save`. Rich ephemeral prints one apply next-step and one failing check (`score: 0`), then one `next: atris youtube teach <same-url>`, and writes no files. Thin ephemeral prints `check: fill this` instead of inventing a check. A playlist or multi-url batch does the same for the first successful item only. A playlist expand that prints video rows keeps them even when yt-dlp exits 429. A notes run that already wrote `yt_<id>.md` keeps that lesson even when the runner exits 429 or a later error, so the learner gate and rich `--save` mint still run. Watch, youtu.be, shorts, embed, live, /e/, and youtube-nocookie embed urls all resolve the same video id, so empty-JSON teach/process and notes keep still find that file. A copied watch?v=&list= URL still finds yt_<video>.en.vtt when -J dumps playlist JSON. A copied #t= timestamp still finds the same yt_<id> file. The bundled ytnotes script does the same for a written manual or auto en, en-orig, en-US, or en-GB VTT plus printed metadata. `--json` stays quiet on the check and the teach next-step. Rich `--save` files the brief, mints `atris/experiments/notes-<id>/`, writes one Apply, and prints `score: 0` only when that Apply starts failing. A rich multi-url `--save` batch proves that failing baseline for the first saved pack only; thin `--save` (no number-with-units and no named mechanism) refuses with no brief and exit 2. Do not auto `--paid`.
84
+ 4. `atris youtube notes URL` after a URL is picked (free). Notes is ephemeral unless `--save`. Rich ephemeral prints one apply next-step and one failing check (`score: 0`), then one `next: atris youtube teach <same-url>`, and writes no files. Thin ephemeral prints `check: fill this` instead of inventing a check. A playlist or multi-url batch does the same for the first successful item only. A playlist expand that prints video rows keeps them even when yt-dlp exits 429. A notes run that already wrote `yt_<id>.md` keeps that lesson even when the runner exits 429 or a later error, so the learner gate and rich `--save` mint still run. Watch, youtu.be, shorts, embed, live, /e/, and youtube-nocookie embed urls all resolve the same video id, so empty-JSON teach/process and notes keep still find that file. A copied watch?v=&list= URL still finds yt_<video>.en.vtt when -J dumps playlist JSON. A copied #t= timestamp still finds the same yt_<id> file. The bundled ytnotes script does the same for a written manual or auto en, en-orig, en-US, or en-GB VTT plus printed metadata, and skips a leaked WARNING/ERROR print line or a NA/None print when choosing the video id. `--json` stays quiet on the check and the teach next-step. Rich `--save` files the brief, mints `atris/experiments/notes-<id>/`, writes one Apply, and prints `score: 0` only when that Apply starts failing. A rich multi-url `--save` batch proves that failing baseline for the first saved pack only; thin `--save` (no number-with-units and no named mechanism) refuses with no brief and exit 2. Do not auto `--paid`.
85
85
  5. Write one Apply (change + receipt) before `atris youtube process`. Process still requires a filled Apply (so you `--save` a rich brief, fill Apply, then process). A rich analysis then mints `atris/experiments/process-<id>/`, writes one pack-named Apply, and prints `score: 0` only when that Apply starts failing. Thin analysis prints `check: fill this`. `--json` stays quiet. 401, 402, or 502 print Credits when present and say credits refunded only when the server marks a refund. A local-transcript 502 that then retries cloud prints those same credit lines from the first payload before the retry. A 401 that remints and retries prints those same credit lines from the first payload before the retry.
86
86
  6. Never paste tokens. Never `/auth/cli`. Mint with `atris login --agent` from a stored login.
87
87
 
@@ -117,7 +117,7 @@ atris youtube search "MCP agents" --json
117
117
 
118
118
  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. A rich hit prints one inferred check plus `score: 0`. A thin hit prints `check: fill this`. Then one next: `atris youtube teach <first-url>`. `--json` stays quiet.
119
119
 
120
- On 429, printed rows are a hit (no retry). If stdout is empty the CLI retries once, then serves `~/.atris/youtube-search-cache.json` if the same query is younger than one hour. A cache reprint prints the same rich or thin check as a live hit. If it prints the rate-limit sentence, stop. Do not run `--paid`.
120
+ On 429, printed rows are a hit (no retry). A leaked WARNING/ERROR/INFO print line or a `youtu.be/NA` / `youtu.be/None` row is not a hit. If stdout is empty the CLI retries once, then serves `~/.atris/youtube-search-cache.json` if the same query is younger than one hour. A cache reprint prints the same rich or thin check as a live hit. If it prints the rate-limit sentence, stop. Do not run `--paid`.
121
121
 
122
122
  ## Paid search (5 credits, opt-in buy only)
123
123
 
@@ -286,8 +286,8 @@ Two layers, never mixed. The reply the person reads is flowing prose: ideas, spe
286
286
  | `502` | Transcript or cloud processing failed | Retry; print credits refunded only when the server marks a refund |
287
287
  | search exit 2 | ytsearch/yt-dlp missing or no results | Install yt-dlp, or put ytsearch on PATH |
288
288
  | search 429 | YouTube rate-limited local search | use printed rows if any; else CLI already retried; use cached rows if printed (same rich/thin check as a live hit); if the rate-limit sentence prints, STOP; do not use --paid |
289
- | teach 429 | YouTube rate-limited local metadata | use printed yt-dlp JSON if it parses; if the caption URL fetch fails or `-J` stdout is empty or broken, use a written VTT or clean.txt from the notes work dir; no written caption still fails; do not use process as a fallback |
290
- | notes 429 | YouTube rate-limited local captions | use a written yt_<id>.md if it exists; ytnotes keeps a written manual or auto en / en-orig / en-US / en-GB VTT plus printed metadata, or a VTT written in the same run when print is empty, including /e/ and youtube-nocookie embed urls; a copied #t= timestamp still finds that leftover file; empty 429 with no captions still fails; do not use --paid |
289
+ | teach 429 | YouTube rate-limited local metadata | use printed yt-dlp JSON if it parses, including when a WARNING/ERROR/INFO line prefixes the dump; if the caption URL fetch fails or `-J` stdout is empty or broken, use a written VTT or leftover same-id clean.txt from the notes work dir; leftover [mm:ss] stamps become cues; another video leftover is not invent-keep; no written caption still fails; do not use process as a fallback |
290
+ | notes 429 | YouTube rate-limited local captions | use a written yt_<id>.md if it exists; ytnotes keeps a written manual or auto en / en-orig / en-US / en-GB VTT plus printed metadata, or a VTT written in the same run when print is empty, including /e/ and youtube-nocookie embed urls; a leaked warning line or NA/None print is not the video id; a copied #t= timestamp still finds that leftover file; empty 429 with no captions still fails; do not use --paid |
291
291
 
292
292
  ---
293
293
 
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, hasYesFlag } = require('../lib/noninteractive');
50
+ const { isHelpToken, argsWantHelp, hasYesFlag, envForcesNonInteractive } = require('../lib/noninteractive');
51
51
 
52
52
  // State detection for smart default
53
53
  const { detectWorkspaceState, loadContext } = require('../lib/state-detection');
@@ -120,7 +120,7 @@ const helpRequested = updateCommand === 'help'
120
120
  const jsonRequested = process.argv.slice(2).includes('--json');
121
121
  const dryRunRequested = updateArgs.includes('--dry-run');
122
122
  const skipUpdateCheck = Boolean(process.env.ATRIS_SKIP_UPDATE_CHECK || process.env.NO_UPDATE_NOTIFIER || helpRequested || jsonRequested);
123
- if (!skipUpdateCheck && (!updateCommand || (updateCommand && !['version', 'update'].includes(updateCommand)))) {
123
+ if (!skipUpdateCheck && (!updateCommand || (updateCommand && !['version', 'update', 'mcp'].includes(updateCommand)))) {
124
124
  updateCheckPromise = checkForUpdates()
125
125
  .then((updateInfo) => {
126
126
  if (updateInfo) {
@@ -577,6 +577,7 @@ function showHelpAll() {
577
577
  console.log(' watch - Turn one sentence into an always-on background watcher');
578
578
  console.log(' ctop - Show a process-first live agent CPU/memory view');
579
579
  console.log(' doctor - Node/task/auth/workspace readiness (--json for agents)');
580
+ console.log(' doc-health - workspace document size, navigation, freshness, and map line refs (--json, --fix-refs)');
580
581
  console.log(' launchpad - Show the next action from local brain, task, mission, and proof state');
581
582
  console.log(' brief - Show the one-glance operator brief');
582
583
  console.log(' status - See local work and completions (`atris status <business>` for remote)');
@@ -627,6 +628,7 @@ function showHelpAll() {
627
628
  console.log(' land - The landing: what is actually done vs still in the air; --reap backs up + clears overdue');
628
629
  console.log(' caretaker - Classify open pull requests on origin (scan only; no fix, comment, or merge)');
629
630
  console.log(' drive - One self-driving tick: mission doctor -> auto-fix -> count disengagements');
631
+ console.log(' rsi - Read the Dream-RSI attempt ledger (trees, attempts, policy, dreams)');
630
632
  console.log(` autoland - Approve the policy once; ${require('../lib/autoland').certifiedWorkLandsPhrase(process.cwd())}, you keep irreversible calls`);
631
633
  console.log(' engine - engine registry, answer validation, dispatch flights, and live progress');
632
634
  console.log(' ci - run github actions jobs locally with runs-on: atris');
@@ -714,6 +716,8 @@ function showHelpAll() {
714
716
  console.log(' usage - Show developer API usage');
715
717
  console.log(' api-key - Create, list, rotate, or revoke a developer API key');
716
718
  console.log(' topup - Buy credits and print a Stripe checkout URL');
719
+ console.log(' design - Extract a site design system, check brand adherence, search brands');
720
+ console.log(' mcp - Run the atris MCP server (stdio) for Claude Desktop and Cursor');
717
721
  console.log('');
718
722
  console.log('Integrations:');
719
723
  console.log(' github - github cli wrapper (doctor, auth, pr list/create/checks/view)');
@@ -1295,8 +1299,7 @@ function useInteractiveAtrisUi() {
1295
1299
  return Boolean(
1296
1300
  process.stdin.isTTY
1297
1301
  && process.stdout.isTTY
1298
- && !process.env.ATRIS_NO_INTERACTIVE
1299
- && process.env.ATRIS_NONINTERACTIVE !== '1'
1302
+ && !envForcesNonInteractive()
1300
1303
  );
1301
1304
  }
1302
1305
 
@@ -1460,7 +1463,7 @@ async function interactiveEntry(userInput, options = {}) {
1460
1463
  : (context.inProgressFeatures || []).length;
1461
1464
 
1462
1465
  // Pull active missions (durable goals), these outrank dev-pipeline state
1463
- // because a mission with an unverified verifier is a Keshav-attributable
1466
+ // because a mission with an unverified verifier is an owner commitment
1464
1467
  // commitment that hasn't been closed yet.
1465
1468
  const activeMissions = loadActiveMissions(workspaceDir);
1466
1469
  const liveMissionsCount = activeMissions.length;
@@ -1633,7 +1636,15 @@ function showWelcomeVisualization() {
1633
1636
  const isInitialized = fs.existsSync(atrisDir);
1634
1637
  let endgameState = { slug: 'unset', horizon: '' };
1635
1638
 
1639
+ let keptCount = 0;
1636
1640
  if (isInitialized) {
1641
+ try {
1642
+ const kept = require('../lib/task-list-keeper').keepWorkspaceTaskList(cwd);
1643
+ keptCount = (kept.put_away || []).length + (kept.reaped || []).length;
1644
+ if (keptCount > 0) require('../commands/task').refreshKeptTaskList(cwd);
1645
+ } catch {
1646
+ keptCount = 0;
1647
+ }
1637
1648
  try {
1638
1649
  glance = getTaskGlance(atrisDir);
1639
1650
  } catch {
@@ -1716,6 +1727,10 @@ function showWelcomeVisualization() {
1716
1727
  // Show the work itself, not counts. A newcomer in any domain (code, docs,
1717
1728
  // a travel plan) should read actual task names and know what's happening.
1718
1729
  // Waiting-on-you comes first: the one thing only a human can do.
1730
+ if (keptCount > 0) {
1731
+ const noun = keptCount === 1 ? 'item' : 'items';
1732
+ console.log(row('kept', `put away ${keptCount} ${noun} that were finished or sitting still`));
1733
+ }
1719
1734
  if (glance.reviewCertified > 0) {
1720
1735
  console.log(row('you', `${glance.reviewCertified} done, waiting for your ok:`));
1721
1736
  glance.certifiedTitles.forEach((t) => console.log(sub(trimTitle(t))));
@@ -1739,6 +1754,18 @@ function showWelcomeVisualization() {
1739
1754
  console.log(row('now', 'nothing on the list yet'));
1740
1755
  }
1741
1756
 
1757
+ try {
1758
+ const health = require('../commands/doc-health').computeDocHealth(cwd);
1759
+ if (health.ok) {
1760
+ const detail = health.lookup_hops.missing
1761
+ ? 'add atris/doc-health/questions.jsonl'
1762
+ : `${Math.round((health.lookup_hops.score || 0) * 100)}% one hop · boot ${(health.boot_load.approximate_tokens / 1000).toFixed(1)}k tokens`;
1763
+ console.log(row('docs', `${health.overall.total}/100 · ${detail}`));
1764
+ }
1765
+ } catch {
1766
+ // Document health is advisory and must never prevent startup.
1767
+ }
1768
+
1742
1769
  // landSummary is expensive (git board classification) - compute once per boot.
1743
1770
  let landInfo = null;
1744
1771
  try { landInfo = require('../commands/land').landSummary(cwd); } catch (err) { landInfo = null; }
@@ -1999,6 +2026,11 @@ if (command === 'guide') {
1999
2026
  Promise.resolve(require('../commands/drive').driveCommand(process.argv.slice(3)))
2000
2027
  .then((code) => process.exit(code || 0))
2001
2028
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2029
+ } else if (command === 'rsi') {
2030
+ // RSI: read the Dream-RSI attempt ledger (trees, attempts, policy, dreams).
2031
+ Promise.resolve(require('../commands/rsi').run(process.argv.slice(3)))
2032
+ .then((code) => process.exit(typeof code === 'number' ? code : 0))
2033
+ .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2002
2034
  } else if (command === 'orb') {
2003
2035
  Promise.resolve(orbCmd(process.argv.slice(3)))
2004
2036
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
@@ -2026,6 +2058,22 @@ if (command === 'guide') {
2026
2058
  Promise.resolve(require('../commands/aeo').run(process.argv.slice(3)))
2027
2059
  .then(() => process.exit(0))
2028
2060
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2061
+ } else if (command === 'design') {
2062
+ // Design: extract a site's design system, check brand adherence, search brands.
2063
+ Promise.resolve(require('../commands/design').run(process.argv.slice(3)))
2064
+ .then((code) => process.exit(typeof code === 'number' ? code : 0))
2065
+ .catch((err) => { console.error(String(err.message || err).replace(/\s+/g, ' ')); process.exit(1); });
2066
+ } else if (command === 'mcp') {
2067
+ // MCP: stdio Model Context Protocol server exposing the design tools.
2068
+ {
2069
+ const serverPath = require('path').join(__dirname, '..', 'mcp', 'atris-mcp', 'index.mjs');
2070
+ const child = require('child_process').spawn(process.execPath, [serverPath, ...process.argv.slice(3)], { stdio: 'inherit' });
2071
+ for (const signal of ['SIGTERM', 'SIGINT']) {
2072
+ process.on(signal, () => { try { child.kill(signal); } catch { /* child already gone */ } });
2073
+ }
2074
+ child.on('error', (err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2075
+ child.on('exit', (code) => process.exit(code == null ? 1 : code));
2076
+ }
2029
2077
  } else if (command === 'improve') {
2030
2078
  // Improve: one paid RL tick via POST /api/improve (deducts credits), local autopilot fallback.
2031
2079
  Promise.resolve(require('../commands/improve').run(process.argv.slice(3)))
@@ -2696,8 +2744,12 @@ if (command === 'guide') {
2696
2744
  });
2697
2745
  } else if (command === 'doctor') {
2698
2746
  Promise.resolve(require('../commands/doctor').doctorCommand(process.argv.slice(3)))
2699
- .then((code) => process.exit(typeof code === 'number' ? code : 0))
2700
- .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2747
+ .then((code) => { process.exitCode = typeof code === 'number' ? code : 0; })
2748
+ .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exitCode = 1; });
2749
+ } else if (command === 'doc-health') {
2750
+ Promise.resolve(require('../commands/doc-health').docHealthCommand(process.argv.slice(3)))
2751
+ .then((code) => { process.exitCode = typeof code === 'number' ? code : 0; })
2752
+ .catch((err) => { console.error(err.message || err); process.exitCode = 1; });
2701
2753
  } else if (command === 'verify') {
2702
2754
  const args = process.argv.slice(3);
2703
2755
  if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
@@ -2906,7 +2958,7 @@ if (command === 'guide') {
2906
2958
  const subcommand = process.argv[3];
2907
2959
  const args = process.argv.slice(4);
2908
2960
  Promise.resolve(require('../commands/member').memberCommand(subcommand, ...args))
2909
- .then(() => process.exit(0))
2961
+ .then(() => process.exit(subcommand === 'run' ? (process.exitCode || 0) : 0))
2910
2962
  .catch((err) => { console.error(`✗ Error: ${err.message || err}`); process.exit(1); });
2911
2963
  } else if (command === 'app') {
2912
2964
  const subcommand = process.argv[3];