atris 3.43.0 → 3.45.1

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 (52) hide show
  1. package/atris/skills/design/SKILL.md +7 -1
  2. package/atris/skills/engines/SKILL.md +44 -13
  3. package/atris/team/customer-lead/MEMBER.md +45 -0
  4. package/atris/team/customer-lead/SOUL.md +33 -0
  5. package/atris/team/customer-lead/START_HERE.md +7 -0
  6. package/atris/team/customer-lead/skills/customer-commitments/SKILL.md +45 -0
  7. package/atris/team/improver/MEMBER.md +33 -0
  8. package/bin/atris.js +36 -3
  9. package/commands/aeo.js +5 -2
  10. package/commands/align.js +5 -2
  11. package/commands/autoland.js +15 -1
  12. package/commands/caretaker.js +303 -0
  13. package/commands/clean.js +76 -0
  14. package/commands/computer.js +5 -2
  15. package/commands/engine-watch.js +212 -0
  16. package/commands/engine.js +99 -11
  17. package/commands/founder.js +304 -0
  18. package/commands/human-missions.js +844 -0
  19. package/commands/improve.js +29 -6
  20. package/commands/init.js +16 -7
  21. package/commands/mission.js +124 -69
  22. package/commands/pull.js +5 -2
  23. package/commands/push.js +5 -2
  24. package/commands/slop.js +34 -3
  25. package/commands/task.js +51 -4
  26. package/commands/team.js +329 -13
  27. package/commands/terminal.js +5 -2
  28. package/commands/verify.js +99 -6
  29. package/commands/workflow.js +10 -3
  30. package/commands/worktree.js +119 -4
  31. package/lib/auto-accept-certified.js +302 -0
  32. package/lib/cloud-mission.js +59 -2
  33. package/lib/conductor-artifacts.js +1 -1
  34. package/lib/dispatch-scout.js +386 -0
  35. package/lib/engine-ask.js +645 -0
  36. package/lib/engine-job-lifecycle.js +65 -0
  37. package/lib/engine-receipt-sweep.js +98 -0
  38. package/lib/engine-registry.js +2 -2
  39. package/lib/engine-validate.js +382 -0
  40. package/lib/fleet.js +459 -106
  41. package/lib/known-commands.js +2 -2
  42. package/lib/member-alive.js +2 -2
  43. package/lib/policy-lessons.js +70 -0
  44. package/lib/receipt-evidence.js +56 -1
  45. package/lib/runner-command.js +1 -1
  46. package/lib/secret-gateway.js +588 -0
  47. package/lib/team-presence.js +13 -1
  48. package/lib/voice-gate.js +6 -0
  49. package/lib/wish-audit.js +5 -205
  50. package/lib/wish-delegate.js +5 -2
  51. package/package.json +6 -1
  52. package/utils/auth.js +56 -9
@@ -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.0.0
4
+ version: 3.1.0
5
5
  allowed-tools: Read, Write, Edit, Bash, Glob
6
6
  tags:
7
7
  - design
@@ -108,6 +108,12 @@ Every entry: id, rule, detector, status. A detector is a regex/command a gate ca
108
108
  | D7 | no em dashes in UI copy or prose | U+2014 scan | graduated (atris slop) |
109
109
  | D8 | no claude-beige backgrounds, no instrument serif as default | judgment | active |
110
110
  | D9 | fuzzy wish gets translated to craft vocabulary and echoed back before building | judgment | active |
111
+ | D10 | measured tokens over vibes: new components start from a measured recipe (exact colors, spacing, radii, type from a proven source), never from scratch | judgment | active |
112
+ | D11 | layout contracts, not dioramas: min-height over fixed height, fluid max-width over fixed px, every overflow reachable (scroll or +N more), stress-test with hostile content before shipping | judgment | active |
113
+ | D12 | one accent moment per card: brand accent for the primary action only, gold for confidence/progress fills, green only for completed; everything else tonal | judgment | active |
114
+ | D13 | motion is calm and eased: 120-300ms ease-out on opacity/transform only, loops match a measured source cadence, prefers-reduced-motion always freezes them | judgment | active |
115
+
116
+ 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.
111
117
 
112
118
  ## Self-Improve (part of the job)
113
119
 
@@ -1,54 +1,85 @@
1
1
  ---
2
2
  name: engines
3
- description: "Dispatch coding work to an installed terminal agent — Codex, Cursor, Devin, Grok, or Atris Fast — as an interchangeable worker engine. Claude orchestrates: writes the bounded prompt, the engine builds, Claude verifies and lands. Triggers on: use codex, use cursor, use devin, use grok, use atris, engine, dispatch to, worker agent, second opinion build."
4
- version: 1.2.0
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 Droid. Triggers on: use codex, use cursor, use devin, use grok, use fable, use claude, use atris, engine, dispatch to, worker agent, second opinion build."
4
+ version: 1.3.1
5
5
  tags:
6
6
  - engines
7
+ - claude
7
8
  - codex
8
9
  - cursor
10
+ - fable
11
+ - composer
12
+ - haiku
9
13
  - devin
10
14
  - grok
15
+ - droid
11
16
  - atris
12
17
  - orchestration
13
18
  ---
14
19
 
15
20
  # Engines — interchangeable terminal workers
16
21
 
17
- One contract, five engines. The orchestrator (you, Claude) writes a bounded task prompt, dispatches it to an engine, then **independently verifies, lands, and pushes** the result. Engines never self-certify.
22
+ One contract, ten 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.
18
23
 
19
- ## Invocation
24
+ ## three verbs
25
+
26
+ - ask: `atris engine <name> "<question>"`; pin a model with `atris engine <name> --model <model> "<question>"`
27
+ - build: `atris engine <name> <task-id>`
28
+ - switch: `atris engine <name>`
29
+
30
+ ## Raw binary fallback and debugging
31
+
32
+ Raw spawns are not the default because they skip Atris receipts, watch, and coaching.
20
33
 
21
34
  | Engine | Command | Notes |
22
35
  |--------|---------|-------|
23
- | Codex | `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task --background [--write] "<prompt>"` (via codex plugin / codex:codex-rescue agent) | Poll with `status`, fetch with `result <job-id>` |
36
+ | 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. |
37
+ | Claude | `claude -p "<prompt>"` | Uses the local Claude configuration. Add `--model opus` for maximum-depth review or `--model sonnet` for speed. |
38
+ | 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) |
24
39
  | Cursor | `cursor-agent --trust -p "<prompt>"` (run from the target repo) | Headless print mode; `--trust` required for non-interactive |
40
+ | Fable | `claude -p "<prompt>" --model opus` | Maximum-depth Claude review. The `fable` Atris profile is the leader lane and uses the installed Claude CLI. |
41
+ | Composer | `atris run "<objective>" --engine composer` | Fast navigator/executor profile routed through the installed `ax` binary. |
42
+ | Haiku | `claude -p "<prompt>" --model claude-haiku-4-5` | Fast validation and bounded read-only checks. |
25
43
  | 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` |
26
- | Grok | `grok --always-approve -p "<prompt>"` (run from the target repo) | Headless single-turn via `-p`; default model grok-4.5. Very fast on lookups (~10s, reads MAP first). Great for quick second opinions; use `--best-of-n <N>` for tricky bounded builds. Uses grok.com login |
27
- | Atris Fast | `atris chat --print "<prompt>"` (run from the target repo; equivalently `ax --fast --print`) | Headless JSON result `{ok, model, output, durationMs}`; exit 0 = ok. Serves via the api.atris.ai fast lane (glm-5.2) with a local tool runtime scoped to the cwd — reads, greps, small verified edits. ~1% of frontier cost, typical turns 5–40s |
44
+ | 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 |
45
+ | Droid | `droid exec "<prompt>"` | Executor profile using Droid's built-in router. Use only when the binary is ready in `atris engine --help`. |
46
+
47
+ 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.
28
48
 
29
49
  ## Picking an engine
30
50
 
51
+ - **Atris Fast** — cheap bounded lookups, single-file facts, small verified edits, and high-volume fan-out.
52
+ - **Claude / Fable** — deep review, synthesis, validation, and complex builds. Use Fable when judgment quality matters most.
31
53
  - **Codex** — deep root-cause work, long autonomous builds, second-opinion diagnosis. Slowest; runs sandboxed.
32
54
  - **Cursor** — fast bounded edits and refactors in a single repo.
55
+ - **Composer / Haiku** — fast, bounded navigation, edits, and validation where a max-tier model would be wasteful.
33
56
  - **Devin** — multi-step feature work; use `cloud` when the run should survive laptop sleep.
34
- - **Grok** - fastest frontier lookups and quick second opinions (grok-4.5, ~10s; reads MAP first); use `--best-of-n` for tricky bounded builds. Uses grok.com login.
35
- - **Atris Fast** — cheap bounded lookups, single-file facts, small verified edits, high-volume fan-out (ten questions = ten `--print` calls at pennies). Not for multi-file features or long builds. Use it before burning a frontier engine on grunt work.
57
+ - **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.
58
+ - **Droid** — executor work through its built-in router when installed.
36
59
  - Parallel builds across repos: one engine job per repo, never two engines writing the same checkout.
37
60
 
38
- ## Models worth pinning (verified live 2026-07-09)
61
+ ## Models worth pinning (verified live 2026-08-12)
39
62
 
40
63
  Each engine CLI can pin a specific model. Current best picks:
41
64
 
42
65
  | Engine | Flag | Best models today |
43
66
  |--------|------|-------------------|
67
+ | Claude / Fable | `--model opus` | `opus` currently resolves to Opus 5; use the explicit Opus 4.8 identifier only for reproducibility |
44
68
  | 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 |
45
- | Cursor | `--model grok-4.5-xhigh` | `grok-4.5-xhigh` / `grok-4.5-fast-xhigh` for second-opinion builds, `composer-2.5` for fast edits; parameterized Claude via `'claude-opus-4-8[effort=high]'`; `--list-models` shows the full menu |
46
- | Grok | (default) | `grok-4.5` default, `grok-composer-2.5-fast` for speed |
47
- | Codex | (plugin default) | rides the codex plugin's pinned model |
69
+ | 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 |
70
+ | Composer | `--engine composer` | `composer 2.5` through the Atris profile |
71
+ | Haiku | `--model claude-haiku-4-5` | `haiku` for fast validation |
72
+ | Grok | (default) | `grok-4.6` default (confirmed live 2026-08-12, ~5s lookup), `grok-4.5` still available via `-m` |
73
+ | Codex | `-m <model>` | CLI default rides `~/.codex/config.toml`; pin with `-m` only when the task needs it |
74
+ | Droid | (built-in router) | Let the installed Droid CLI select its model |
48
75
  | Atris Fast | (fixed) | api.atris.ai fast lane |
49
76
 
50
77
  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.
51
78
 
79
+ ## Keep the local roster current
80
+
81
+ Run `atris engine doctor`, then `atris engine --help`. The canonical profiles live in `lib/runner-command.js`; tiers, roles, models, duties, and health live in `lib/engine-registry.js`. When this guide and the live roster disagree, the registry is the source of truth and this guide must be updated.
82
+
52
83
  ## Atris Fast runtime requirements (verified live 2026-07-03)
53
84
 
54
85
  - 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"}`.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: customer-lead
3
+ role: Customer Lead
4
+ description: Keeps customer commitments visible, spots retention risk, and turns evidence into the next useful follow-up.
5
+ version: 1.0.0
6
+
7
+ skills:
8
+ - customer-commitments
9
+
10
+ permissions:
11
+ can-read: true
12
+ can-execute: true
13
+ can-approve: false
14
+ can-send: false
15
+ approval-required:
16
+ - send
17
+ - publish
18
+ - commercial-promise
19
+
20
+ tools: []
21
+ ---
22
+
23
+ # Customer Lead
24
+
25
+ ## Persona
26
+
27
+ Warm, concise, and exact about follow-through. Customer Lead starts with what
28
+ the customer is trying to achieve, separates evidence from assumptions, and
29
+ raises a broken commitment before it becomes a broken relationship.
30
+
31
+ ## Workflow
32
+
33
+ 1. Read the available customer messages, feedback, notes, tasks, and receipts.
34
+ 2. Name the desired outcome, latest signal, open commitment, owner, due date, and evidence for each customer in scope.
35
+ 3. Mark each commitment on track, needs attention, broken, or unknown without inventing a health score.
36
+ 4. Draft the smallest recovery or follow-up that moves the customer's outcome forward, routing product work into the existing task or feedback queue.
37
+ 5. Record the next commitment and proof target, then ask for human approval before any external message or commercial promise.
38
+
39
+ ## Rules
40
+
41
+ 1. Never send a message, issue a credit, or promise price, timing, or roadmap work without human approval.
42
+ 2. Use real evidence only. Missing data stays unknown, and silence alone is not proof of churn.
43
+ 3. Own customer outcomes, commitments, and retention risk, not prospecting or product-feedback synthesis.
44
+ 4. Prefer one clear next commitment over account theater, generic check-ins, or a heavyweight review process.
45
+ 5. Expansion follows proven value and explicit customer need; never push it to repair weak retention.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: customer-lead
3
+ version: 1.0.0
4
+ born: 2026-08-11
5
+ ---
6
+
7
+ # Soul
8
+
9
+ ## Beliefs
10
+
11
+ - Customers experience the company through the promises it keeps.
12
+ - A small missed commitment can predict lost trust earlier than a large dashboard.
13
+ - Unknown evidence should remain unknown until a real signal resolves it.
14
+ - Retention is earned by useful outcomes and honest follow-through, not by more meetings.
15
+
16
+ ## Values
17
+
18
+ 1. Trust through follow-through.
19
+ 2. Early, grounded evidence.
20
+ 3. Restraint before external action.
21
+
22
+ ## Lessons
23
+
24
+ - No earned lessons yet.
25
+
26
+ ## Edges
27
+
28
+ - **Strong:** Turns scattered customer signals into explicit owners, dates, risks, and next actions.
29
+ - **Weak:** Can overread silence or loud feedback, so it seeks confirmation before escalating a conclusion.
30
+
31
+ ## Voice
32
+
33
+ - What did we promise, what evidence says it helped, and what must happen next?
@@ -0,0 +1,7 @@
1
+ # Start Here - Customer Lead
2
+
3
+ 1. Read the current customer evidence and name which customer or segment is in scope.
4
+ 2. Open the existing feedback and task queues so customer work is not duplicated.
5
+ 3. Build the commitment view with an outcome, evidence, owner, due date, state, and next action.
6
+ 4. Draft one useful follow-up or recovery step and stop for approval before anything leaves the workspace.
7
+ 5. Close with the commitment recorded and a proof target for the next check.
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: customer-commitments
3
+ description: Turn real customer evidence into a compact commitment view, retention risk, and one approval-gated next action. Use when reviewing customer feedback, follow-ups, promises, churn signals, or retention risk.
4
+ version: 1.0.0
5
+ tags:
6
+ - customer-success
7
+ - retention
8
+ - commitments
9
+ ---
10
+
11
+ # Customer Commitments
12
+
13
+ Use this skill when a customer outcome, promise, follow-up, or retention risk
14
+ needs an owner and a trustworthy next action.
15
+
16
+ ## Workflow
17
+
18
+ 1. Read only the customer evidence available in the workspace.
19
+ 2. Record the customer, desired outcome, latest signal, commitment, owner, due date, state, source, and confidence.
20
+ 3. Use only four states: on track, needs attention, broken, or unknown.
21
+ 4. Draft one next action tied to the desired outcome and existing evidence.
22
+ 5. Route product defects or requests into the existing feedback or task system.
23
+ 6. Stop for human approval before sending, publishing, discounting, refunding, or making a commercial or roadmap promise.
24
+
25
+ ## Guardrails
26
+
27
+ - Never manufacture usage, sentiment, renewal, or revenue data.
28
+ - Never replace missing evidence with a composite health score.
29
+ - Never create a parallel product backlog from customer notes.
30
+ - Keep the view small enough that an owner can see the next commitment immediately.
31
+
32
+ ## Example
33
+
34
+ Input: "The customer asked about exports last week, and we promised an answer by Friday."
35
+
36
+ Output: Record the customer's export outcome, the dated request as evidence,
37
+ the promised answer and its owner, Friday as the due date, the state as needs
38
+ attention, and one approval-gated follow-up. Leave any missing owner or customer
39
+ sentiment unknown.
40
+
41
+ ## Troubleshooting
42
+
43
+ - If sources conflict, show both signals, lower confidence, and ask the owner to resolve them.
44
+ - If no owner or due date exists, mark it unknown and propose one for approval.
45
+ - If the next action is product work, link or update the existing task instead of opening a parallel backlog.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: improver
3
+ role: Improver
4
+ description: Proposes guarded member and workflow improvements from evidence.
5
+ version: 1.0.0
6
+ runtime-alias: architect
7
+
8
+ skills: []
9
+
10
+ permissions:
11
+ can-read: true
12
+ can-execute: true
13
+ can-approve: false
14
+
15
+ tools: []
16
+ ---
17
+
18
+ # Improver
19
+
20
+ Suggests better member behavior without applying risky changes automatically.
21
+
22
+ ## Workflow
23
+
24
+ 1. Read causal evidence, reusable patterns, logs, and receipts.
25
+ 2. Pick one behavior or workflow improvement.
26
+ 3. Propose a small overlay or task.
27
+ 4. Wait for approval before changing durable member specs.
28
+
29
+ ## Rules
30
+
31
+ - Advisory by default.
32
+ - Prefer overlays over base spec rewrites.
33
+ - Every recommendation needs evidence and a rollback path.
package/bin/atris.js CHANGED
@@ -465,6 +465,13 @@ function showHelp() {
465
465
  console.log(' atris init [--yes] Global install: initialize this project');
466
466
  console.log(' npx atris init [--yes] Local install: initialize this project');
467
467
  console.log(' atris computer');
468
+ console.log(' atris ask "what you want" [--budget <usd>]');
469
+ console.log(' atris mission Show the current mission');
470
+ console.log(' atris approve Approve the step waiting for you');
471
+ console.log(' atris stop Stop the current mission');
472
+ console.log(' atris check <run-id> Show the checks for a mission');
473
+ console.log(' atris ready --json Show which mission features are ready');
474
+ console.log(' atris engine validate latest check the newest ask receipt with a cheap referee');
468
475
  console.log(' atris business init "My Company"');
469
476
  console.log(' atris run');
470
477
  console.log(' atris drill');
@@ -500,6 +507,7 @@ function showHelp() {
500
507
  console.log(' wish - Say one plain sentence, then Atris asks only for gaps or delegates it');
501
508
  console.log(' now - Show atris/now.md, the current operating truth');
502
509
  console.log(' goal - goal, distance, and what moved today (alias: wtf)');
510
+ console.log(' founder - show weekly commit and completed-task improvement from receipts');
503
511
  console.log(' orb - Pick next moves while engine jobs work in the background');
504
512
  console.log(' activate - Load Atris context');
505
513
  console.log(' radar - Show live agents joined with tasks, missions, and worktrees');
@@ -553,9 +561,10 @@ function showHelp() {
553
561
  console.log(' improve - Run one paid RL tick (POST /api/improve, deducts credits)');
554
562
  console.log(' worktree - Isolated Git worktrees plus guarded ship/merge for parallel agents');
555
563
  console.log(' land - The landing: what is actually done vs still in the air; --reap backs up + clears overdue');
564
+ console.log(' caretaker - Classify open pull requests on origin (scan only; no fix, comment, or merge)');
556
565
  console.log(' drive - One self-driving tick: mission doctor -> auto-fix -> count disengagements');
557
566
  console.log(` autoland - Approve the policy once; ${require('../lib/autoland').certifiedWorkLandsPhrase(process.cwd())}, you keep irreversible calls`);
558
- console.log(' engine - Engine registry: list/resolve roles, health flips, default engine, `engine test`, and dispatch flights');
567
+ console.log(' engine - engine registry, answer validation, dispatch flights, and live progress');
559
568
  console.log(' router - inspect ax lane outcomes and promote gated reflex overrides');
560
569
  console.log(' sign - Co-author trailer on every commit in an atris workspace (on/off/status)');
561
570
  console.log(' visualize - Generate a Slack/deck-ready visual from a prompt');
@@ -1844,6 +1853,22 @@ if (command === 'init') {
1844
1853
  Promise.resolve(require('../commands/decide').decideCommand(process.argv.slice(3)))
1845
1854
  .then(() => exitAfterStdoutDrain(process.exitCode || 0))
1846
1855
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); exitAfterStdoutDrain(1); });
1856
+ } else if (
1857
+ ['ask', 'approve', 'stop', 'ready', 'check'].includes(command)
1858
+ || (command === 'proof' && process.argv.slice(3).every((value) => String(value).startsWith('-')))
1859
+ ) {
1860
+ const humanCommands = require('../commands/human-missions');
1861
+ const handlers = {
1862
+ ask: humanCommands.askCommand,
1863
+ approve: humanCommands.approveCommand,
1864
+ stop: humanCommands.stopCommand,
1865
+ ready: humanCommands.readyCommand,
1866
+ check: humanCommands.checkCommand,
1867
+ proof: humanCommands.proofCommand,
1868
+ };
1869
+ Promise.resolve(handlers[command](process.argv.slice(3)))
1870
+ .then((code) => exitWhenFlushed(Number.isInteger(code) ? code : (process.exitCode || 0)))
1871
+ .catch((err) => { console.error(`\nAtris could not finish that request: ${err.message || err}`); exitWhenFlushed(1); });
1847
1872
  } else if (command === 'mission') {
1848
1873
  // process.exit() can outrun a piped stdout: writes beyond the 64KB pipe
1849
1874
  // buffer are async, so large --json payloads truncate at 64KB multiples.
@@ -1886,6 +1911,10 @@ if (command === 'init') {
1886
1911
  Promise.resolve(require('../commands/land').landCommand(process.argv.slice(3)))
1887
1912
  .then((code) => process.exit(code || 0))
1888
1913
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
1914
+ } else if (command === 'caretaker') {
1915
+ Promise.resolve(require('../commands/caretaker').caretakerCommand(process.argv.slice(3)))
1916
+ .then((code) => process.exit(typeof code === 'number' ? code : 0))
1917
+ .catch((err) => { console.error(`\nerror: ${err.message || err}`); process.exit(1); });
1889
1918
  } else if (command === 'close') {
1890
1919
  Promise.resolve(require('../commands/close').run(process.argv.slice(3)))
1891
1920
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
@@ -1894,6 +1923,10 @@ if (command === 'init') {
1894
1923
  Promise.resolve(require('../commands/goal').run(process.argv.slice(3)))
1895
1924
  .then((code) => process.exit(typeof code === 'number' ? code : 0))
1896
1925
  .catch((err) => { console.error(`\nerror: ${err.message || err}`); process.exit(1); });
1926
+ } else if (command === 'founder') {
1927
+ Promise.resolve(require('../commands/founder').founderCommand(process.argv.slice(3)))
1928
+ .then((code) => process.exit(typeof code === 'number' ? code : 0))
1929
+ .catch((err) => { console.error(`\nerror: ${err.message || err}`); process.exit(1); });
1897
1930
  } else if (command === 'drive') {
1898
1931
  // Drive: one self-driving tick — mission doctor -> auto-fix safe findings -> count disengagements.
1899
1932
  Promise.resolve(require('../commands/drive').driveCommand(process.argv.slice(3)))
@@ -2821,9 +2854,9 @@ if (command === 'init') {
2821
2854
  .then(() => process.exit(process.exitCode || 0))
2822
2855
  .catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
2823
2856
  } else if (command === 'engine' || command === 'engines') {
2824
- // Engine: bring any intelligence — roster of installed coding CLIs, default
2857
+ // Engine: bring any intelligence. Roster of installed coding CLIs, default
2825
2858
  // engine per workspace, --engine <name> rides any loop for one run.
2826
- // `engine dispatch` runs an async claim -> build -> ship flight, so the
2859
+ // `engine dispatch`, `engine ask`, `engine validate`, and `engine watch` can be async, so the
2827
2860
  // return value may be a promise or a plain number; Promise.resolve handles
2828
2861
  // both (mirrors the `compile` command dispatch just above).
2829
2862
  const engineArgs = command === 'engines' && process.argv.length <= 3 ? [] : process.argv.slice(3);
package/commands/aeo.js CHANGED
@@ -22,7 +22,7 @@ const fs = require('fs');
22
22
  const os = require('os');
23
23
  const path = require('path');
24
24
  const { spawnSync } = require('child_process');
25
- const { loadCredentials } = require('../utils/auth');
25
+ const { loadCredentials, abortOnAuthFailure } = require('../utils/auth');
26
26
  const { apiRequestJson } = require('../utils/api');
27
27
  const { loadBusinesses, saveBusinesses } = require('./business');
28
28
 
@@ -97,13 +97,16 @@ function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
97
97
 
98
98
  async function ensureAwake(token, businessId, maxWaitSec = 90) {
99
99
  const status = await apiRequestJson(`/business/${businessId}/ai-computer/status`, { method: 'GET', token });
100
+ abortOnAuthFailure(status);
100
101
  if (status.ok && status.data && status.data.status === 'running' && status.data.endpoint) return true;
101
102
  process.stdout.write(' Waking EC2 computer... ');
102
- await apiRequestJson(`/business/${businessId}/ai-computer/wake`, { method: 'POST', token });
103
+ const wake = await apiRequestJson(`/business/${businessId}/ai-computer/wake`, { method: 'POST', token });
104
+ abortOnAuthFailure(wake, true);
103
105
  const start = Date.now();
104
106
  while (Date.now() - start < maxWaitSec * 1000) {
105
107
  await sleep(3000);
106
108
  const s = await apiRequestJson(`/business/${businessId}/ai-computer/status`, { method: 'GET', token });
109
+ abortOnAuthFailure(s, true);
107
110
  if (s.ok && s.data && s.data.status === 'running' && s.data.endpoint) {
108
111
  console.log(`awake (${Math.floor((Date.now() - start) / 1000)}s)`);
109
112
  return true;
package/commands/align.js CHANGED
@@ -21,7 +21,7 @@
21
21
  const fs = require('fs');
22
22
  const path = require('path');
23
23
  const crypto = require('crypto');
24
- const { loadCredentials } = require('../utils/auth');
24
+ const { loadCredentials, abortOnAuthFailure } = require('../utils/auth');
25
25
  const { apiRequestJson } = require('../utils/api');
26
26
  const { loadBusinesses, saveBusinesses } = require('./business');
27
27
 
@@ -179,17 +179,20 @@ async function walkCloud(token, businessId, workspaceId) {
179
179
  */
180
180
  async function ensureAwake(token, businessId, maxWaitSec = 90) {
181
181
  const status = await apiRequestJson(`/business/${businessId}/ai-computer/status`, { method: 'GET', token });
182
+ abortOnAuthFailure(status);
182
183
  if (status.ok && status.data && status.data.status === 'running' && status.data.endpoint) {
183
184
  return status.data.endpoint;
184
185
  }
185
186
 
186
187
  process.stdout.write(' Waking EC2 computer... ');
187
- await apiRequestJson(`/business/${businessId}/ai-computer/wake`, { method: 'POST', token });
188
+ const wake = await apiRequestJson(`/business/${businessId}/ai-computer/wake`, { method: 'POST', token });
189
+ abortOnAuthFailure(wake, true);
188
190
 
189
191
  const start = Date.now();
190
192
  while (Date.now() - start < maxWaitSec * 1000) {
191
193
  await sleep(3000);
192
194
  const s = await apiRequestJson(`/business/${businessId}/ai-computer/status`, { method: 'GET', token });
195
+ abortOnAuthFailure(s, true);
193
196
  if (s.ok && s.data && s.data.status === 'running' && s.data.endpoint) {
194
197
  const elapsed = Math.floor((Date.now() - start) / 1000);
195
198
  console.log(`awake (${elapsed}s)`);
@@ -8,6 +8,7 @@ const { spawnSync } = require('child_process');
8
8
  const autoland = require('../lib/autoland');
9
9
  const { gateForHuman, plainLandingReason } = require('../lib/voice-gate');
10
10
  const { evaluateAutoAccept } = require('../lib/auto-accept-certified');
11
+ const { sweepEngineAskReceipts } = require('../lib/engine-receipt-sweep');
11
12
  const { operatorReady, hasAgentJargon, explainResult } = autoland;
12
13
  const MISSION_AUTO_VERIFY_STATUSES = new Set(['planning', 'paused', 'ready']);
13
14
  const CLOSED_TASK_STATUSES = new Set(['done', 'archived']);
@@ -713,8 +714,20 @@ function digestTickStatus(receipt) {
713
714
  return 'not due';
714
715
  }
715
716
 
717
+ function engineReceiptSweepNote(receipt) {
718
+ const finalized = Number(receipt.engine_receipt_sweep?.finalized) || 0;
719
+ if (!finalized) return '';
720
+ return `, finalized ${finalized} stale engine receipt${finalized === 1 ? '' : 's'} as presumed dead`;
721
+ }
722
+
716
723
  function runTickBody(root, { json, policy, receipt }) {
717
724
 
725
+ try {
726
+ receipt.engine_receipt_sweep = sweepEngineAskReceipts(root);
727
+ } catch (err) {
728
+ receipt.engine_receipt_sweep_error = String((err && err.message) || err).slice(0, 200);
729
+ }
730
+
718
731
  // 1. certify and land in one task process. Keeping both phases together lets
719
732
  // the landing gate reuse the live certification verifier result without
720
733
  // persisting trust across heartbeats. Denied lanes and check-less proofs wait.
@@ -983,13 +996,14 @@ function runTickBody(root, { json, policy, receipt }) {
983
996
  const janitorNote = `, janitor stopped ${receipt.missions_stopped} mission${receipt.missions_stopped === 1 ? '' : 's'} + reaped ${receipt.worktrees_reaped} worktree${receipt.worktrees_reaped === 1 ? '' : 's'}`;
984
997
  const heldNote = receipt.missions_held ? `, held ${receipt.missions_held} human-blocked mission${receipt.missions_held === 1 ? '' : 's'}` : '';
985
998
  const wishNote = `, ${wishSweepSummaryLine(receipt.wish_dispatch, receipt.wish_dispatch_error)}`;
999
+ const engineSweepNote = engineReceiptSweepNote(receipt);
986
1000
  const receiptNote = receipt.receipt_path ? `, receipt ${receipt.receipt_path}` : '';
987
1001
  // Deltas alone ("0 certified, 0 landed") are true and useless: they read
988
1002
  // as "nothing to do" whether the queue is empty or 19-deep and wedged.
989
1003
  // Always print the standing backlog, and name work that cleared every
990
1004
  // gate and still did not land — that is the shape of a stuck loop.
991
1005
  const stuckNote = stuckBacklogNote(receipt);
992
- const summary = `autoland tick: ${receipt.reviews_certified ?? 0} reviews certified, ${receipt.landed.length} landed${receipt.landed.length ? ` (${receipt.landed.join(', ')})` : ''}, ${receipt.alarms} alarms${stuckNote}, digest ${digestTickStatus(receipt)}${reapNote}${janitorNote}${heldNote}${wishNote}${receiptNote}`;
1006
+ const summary = `autoland tick: ${receipt.reviews_certified ?? 0} reviews certified, ${receipt.landed.length} landed${receipt.landed.length ? ` (${receipt.landed.join(', ')})` : ''}, ${receipt.alarms} alarms${stuckNote}, digest ${digestTickStatus(receipt)}${reapNote}${janitorNote}${heldNote}${wishNote}${engineSweepNote}${receiptNote}`;
993
1007
  console.log(gateForHuman(summary).text);
994
1008
  for (const fulfilled of receipt.wish_dispatch?.fulfilled_results || []) {
995
1009
  if (fulfilled.review_ask) console.log(fulfilled.review_ask);