atris 3.57.4 → 3.58.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/atris/skills/clawhub/member-runtime/SKILL.md +9 -9
- package/atris/skills/create-member/SKILL.md +16 -13
- package/atris/skills/design/SKILL.md +27 -4
- package/atris/skills/engines/SKILL.md +55 -12
- package/atris/skills/x-search/SKILL.md +8 -6
- package/atris/skills/youtube/SKILL.md +37 -8
- package/atris/team/brainstormer/MEMBER.md +2 -2
- package/atris/team/executor/MEMBER.md +3 -3
- package/atris/team/launcher/MEMBER.md +4 -4
- package/atris/team/navigator/MEMBER.md +3 -3
- package/atris/team/researcher/MEMBER.md +2 -2
- package/atris/team/validator/MEMBER.md +1 -1
- package/atris.md +14 -0
- package/ax +153 -23
- package/bin/atris.js +78 -30
- package/commands/aeo.js +4 -4
- package/commands/agents.js +1 -1
- package/commands/align.js +12 -12
- package/commands/analytics.js +3 -3
- package/commands/app.js +5 -5
- package/commands/ask.js +175 -0
- package/commands/auth.js +7 -7
- package/commands/autoland.js +29 -5
- package/commands/autopilot-front.js +6 -6
- package/commands/autopilot.js +90 -90
- package/commands/avail.js +5 -5
- package/commands/bench.js +63 -1
- package/commands/browse.js +2 -2
- package/commands/business.js +12 -12
- package/commands/card.js +2 -2
- package/commands/clean.js +13 -13
- package/commands/close.js +3 -3
- package/commands/compile.js +13 -13
- package/commands/computer.js +94 -27
- package/commands/console.js +5 -5
- package/commands/decide.js +1 -1
- package/commands/deck.js +9 -9
- package/commands/drive.js +4 -4
- package/commands/engine.js +173 -19
- package/commands/errors.js +3 -3
- package/commands/experiments.js +18 -1
- package/commands/feed.js +2 -2
- package/commands/feedback.js +4 -4
- package/commands/fleet.js +12 -12
- package/commands/game.js +1 -1
- package/commands/guide.js +49 -0
- package/commands/improve.js +19 -17
- package/commands/init.js +67 -19
- package/commands/interview.js +7 -7
- package/commands/land.js +40 -15
- package/commands/learn.js +12 -12
- package/commands/lesson.js +2 -2
- package/commands/log.js +1 -1
- package/commands/loops.js +4 -4
- package/commands/member.js +75 -50
- package/commands/mission.js +90 -82
- package/commands/one-lap.js +1 -1
- package/commands/pack.js +74 -8
- package/commands/plugin.js +6 -6
- package/commands/probe.js +9 -9
- package/commands/pull.js +35 -35
- package/commands/pulse.js +1 -1
- package/commands/push.js +21 -21
- package/commands/rainmaker.js +1 -1
- package/commands/recap.js +7 -7
- package/commands/reel.js +2 -2
- package/commands/release.js +3 -3
- package/commands/report.js +1 -1
- package/commands/review.js +5 -5
- package/commands/revisions.js +1 -1
- package/commands/run.js +1 -1
- package/commands/scout.js +3 -3
- package/commands/security-review.js +7 -7
- package/commands/serve.js +9 -9
- package/commands/setup.js +1 -1
- package/commands/sign.js +4 -4
- package/commands/signup.js +4 -4
- package/commands/site.js +8 -3
- package/commands/skill.js +6 -6
- package/commands/slop.js +18 -18
- package/commands/social.js +3 -3
- package/commands/soul.js +14 -14
- package/commands/spaceship.js +1 -1
- package/commands/status.js +2 -2
- package/commands/strings.js +13 -13
- package/commands/study.js +4 -4
- package/commands/sync.js +8 -8
- package/commands/task.js +50 -25
- package/commands/teach.js +2 -2
- package/commands/team.js +1 -1
- package/commands/theme.js +2 -2
- package/commands/tree.js +34 -0
- package/commands/truth.js +7 -7
- package/commands/verify.js +12 -12
- package/commands/visualize.js +2 -2
- package/commands/workflow.js +97 -40
- package/commands/worktree.js +1 -1
- package/commands/write.js +9 -9
- package/commands/x-search.js +89 -17
- package/commands/xp.js +6 -3
- package/commands/youtube.js +601 -48
- package/lib/accept-verify-gate.js +3 -3
- package/lib/activity-stream.js +1 -1
- package/lib/auto-accept-certified.js +28 -12
- package/lib/autoland.js +6 -6
- package/lib/bench/engines.js +59 -8
- package/lib/bench/report.js +1 -1
- package/lib/bench/runner.js +204 -5
- package/lib/bench/tree-render.js +76 -0
- package/lib/card.js +1 -1
- package/lib/chat-log-scan.js +1 -1
- package/lib/claude-boot-block.js +2 -0
- package/lib/deck-compose.js +1 -1
- package/lib/deck-history.js +2 -2
- package/lib/deck-layout.js +1 -1
- package/lib/deck-review.js +5 -5
- package/lib/deck-schema.js +1 -1
- package/lib/default-verifier.js +1 -1
- package/lib/developer-api.js +3 -0
- package/lib/engine-ask.js +45 -7
- package/lib/engine-registry.js +15 -2
- package/lib/file-ops.js +1 -1
- package/lib/fleet.js +71 -35
- package/lib/html-render.js +1 -1
- package/lib/intents.js +172 -0
- package/lib/journal.js +1 -1
- package/lib/known-commands.js +2 -2
- package/lib/land-green.js +364 -0
- package/lib/lesson-contradiction.js +2 -2
- package/lib/lesson-preflight.js +1 -1
- package/lib/manifest.js +5 -5
- package/lib/member-alive.js +9 -5
- package/lib/memory-view.js +3 -3
- package/lib/mission-protected-lane.js +1 -1
- package/lib/mission-root.js +2 -2
- package/lib/orb-context.js +10 -10
- package/lib/pack-capabilities.js +861 -3
- package/lib/permission-grants.js +2 -2
- package/lib/policy-lessons.js +6 -6
- package/lib/pulse.js +8 -8
- package/lib/receipt-evidence.js +1 -1
- package/lib/reel.js +1 -1
- package/lib/review-integrity.js +1 -1
- package/lib/runner-command.js +35 -5
- package/lib/scorecard.js +4 -4
- package/lib/security-scan.js +5 -5
- package/lib/self-drive.js +1 -1
- package/lib/site-publish.js +372 -0
- package/lib/site.js +1 -1
- package/lib/slides-deck.js +2 -2
- package/lib/state-detection.js +2 -2
- package/lib/sync-telemetry.js +2 -2
- package/lib/task-db.js +17 -10
- package/lib/task-explanation.js +1 -1
- package/lib/task-proof.js +2 -2
- package/lib/task-receipt.js +3 -3
- package/lib/theme.js +12 -12
- package/lib/todo-fallback.js +3 -3
- package/lib/todo-sections.js +1 -1
- package/lib/tree-hash.js +79 -0
- package/lib/usage.js +1 -1
- package/lib/wish-delegate.js +1 -1
- package/lib/workspace-safety.js +4 -4
- package/lib/workspace-scaffold.js +3 -3
- package/package.json +1 -1
- package/scripts/det/concierge-bakeoff.sh +26 -0
- package/scripts/det/ytquote-repair.js +0 -1
- package/scripts/det/ytrail-race.js +0 -5
- package/scripts/member-operate.mjs +52 -14
- package/scripts/outbound-artifact-gate.js +0 -3
- package/utils/auth.js +0 -3
- package/utils/config.js +0 -1
- package/scripts/det/checklist-score.js +0 -191
package/lib/engine-registry.js
CHANGED
|
@@ -7,6 +7,7 @@ const {
|
|
|
7
7
|
RUNNER_PROFILE_DEFS,
|
|
8
8
|
RUNNER_PROFILE_ALIASES,
|
|
9
9
|
RUNNER_PROFILE_NAMES,
|
|
10
|
+
HIDDEN_PROFILE_NAMES,
|
|
10
11
|
} = require('./runner-command');
|
|
11
12
|
const { rankEnginesDetailed, routerPickExplanation } = require('./router-brain');
|
|
12
13
|
|
|
@@ -53,6 +54,7 @@ const ENGINE_SEED_META = Object.freeze({
|
|
|
53
54
|
tier: 'pro',
|
|
54
55
|
roles: Object.freeze(['executor']),
|
|
55
56
|
models: Object.freeze([
|
|
57
|
+
'gemini-3.8-flash-high',
|
|
56
58
|
'gemini-3.7-flash-high',
|
|
57
59
|
'gemini-3.1-pro-high',
|
|
58
60
|
'claude-sonnet-4-6',
|
|
@@ -62,6 +64,15 @@ const ENGINE_SEED_META = Object.freeze({
|
|
|
62
64
|
duty: 'errands',
|
|
63
65
|
fallback_order: 90,
|
|
64
66
|
}),
|
|
67
|
+
opencode: Object.freeze({ tier: 'pro', roles: Object.freeze(['executor']), models: Object.freeze(['opencode/big-pickle', 'opencode/claude-opus-4-8', 'opencode/gpt-5.2']), fallback_order: 95 }),
|
|
68
|
+
commandcode: Object.freeze({
|
|
69
|
+
tier: 'max',
|
|
70
|
+
roles: Object.freeze(['validator', 'executor']),
|
|
71
|
+
// No pinned model: the engine rides this machine's Command Code default.
|
|
72
|
+
models: Object.freeze(['machine default']),
|
|
73
|
+
duty: 'errands',
|
|
74
|
+
fallback_order: 98,
|
|
75
|
+
}),
|
|
65
76
|
});
|
|
66
77
|
|
|
67
78
|
function engineRegistryFile(root = process.cwd()) {
|
|
@@ -176,7 +187,9 @@ function seededRegistry(root = process.cwd(), preloadedRaw = null) {
|
|
|
176
187
|
return {
|
|
177
188
|
schema: ENGINE_REGISTRY_SCHEMA,
|
|
178
189
|
updated_at: new Date().toISOString(),
|
|
179
|
-
engines:
|
|
190
|
+
// Hidden profiles are registered engines too: they seed, route, and take
|
|
191
|
+
// health policy exactly like visible ones.
|
|
192
|
+
engines: Object.keys(RUNNER_PROFILE_DEFS).map((id) => normalizeEngineEntry(id, savedById.get(id) || {})),
|
|
180
193
|
};
|
|
181
194
|
}
|
|
182
195
|
|
|
@@ -192,7 +205,7 @@ function writeEngineRegistry(root, registry) {
|
|
|
192
205
|
|
|
193
206
|
function setEngineOverrides(name, overrides = {}, root = process.cwd()) {
|
|
194
207
|
const id = canonicalEngineName(name);
|
|
195
|
-
const knownIds =
|
|
208
|
+
const knownIds = Object.keys(RUNNER_PROFILE_DEFS).filter((engineId) => ENGINE_SEED_META[engineId]);
|
|
196
209
|
if (!id || !knownIds.includes(id)) {
|
|
197
210
|
throw new Error(`Unknown engine "${name}". Known engines: ${knownIds.join(', ')}`);
|
|
198
211
|
}
|
package/lib/file-ops.js
CHANGED
|
@@ -83,7 +83,7 @@ function createLogFile(logFile, dateFormatted) {
|
|
|
83
83
|
const backlogBody = carryBacklog ? `${carryBacklog}\n\n` : '';
|
|
84
84
|
const inboxBody = carryInbox ? `${carryInbox}\n\n` : '';
|
|
85
85
|
|
|
86
|
-
const initialContent = `# Log
|
|
86
|
+
const initialContent = `# Log, ${dateFormatted}\n\n## Handoff\n\n---\n\n## Completed ✅\n\n---\n\n## In Progress 🔄\n\n${inProgressBody}---\n\n## Backlog\n\n${backlogBody}---\n\n## Notes\n\n---\n\n## Inbox\n\n${inboxBody}\n`;
|
|
87
87
|
fs.writeFileSync(logFile, initialContent);
|
|
88
88
|
}
|
|
89
89
|
|
package/lib/fleet.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
// --fleet`), the full loop inside: staff every idle engine on claimable
|
|
5
5
|
// safe-lane tasks, one mission per task, one worktree per engine, land
|
|
6
6
|
// arrivals serially. Proven by hand on 2026-07-02 (PRs #191-193, three
|
|
7
|
-
// engines) before any of this code existed
|
|
7
|
+
// engines) before any of this code existed, each function here is one thing
|
|
8
8
|
// the orchestrator did manually that day.
|
|
9
9
|
//
|
|
10
10
|
// INVARIANT: the fleet has NO state file. Flight state IS missions +
|
|
11
|
-
// worktrees + receipts. Kill a flight mid-run and nothing is orphaned
|
|
11
|
+
// worktrees + receipts. Kill a flight mid-run and nothing is orphaned, it
|
|
12
12
|
// is just missions in flight, resumable the normal way.
|
|
13
13
|
|
|
14
14
|
const fs = require('fs');
|
|
@@ -48,7 +48,7 @@ const { appendEngineLiveLogChunk, createEngineLiveLog, engineTerminalReason } =
|
|
|
48
48
|
const DENIED_TAGS = ['billing', 'money', 'payments', 'deploy', 'security', 'customer', 'external', 'feedback'];
|
|
49
49
|
|
|
50
50
|
// ---------------------------------------------------------------------------
|
|
51
|
-
// T1
|
|
51
|
+
// T1: dispatch primitive
|
|
52
52
|
|
|
53
53
|
// A task's own text is its spec: the board convention writes "Done: ..." and
|
|
54
54
|
// "Check: ..." into the title/description. Extract both so the dispatch
|
|
@@ -68,10 +68,10 @@ function parseDoneCheck(text) {
|
|
|
68
68
|
// hypothesis-driven unsticking, smallest diff.
|
|
69
69
|
const METHOD_KERNEL = [
|
|
70
70
|
'Read this whole brief before acting; locate every file you will touch before editing any of them.',
|
|
71
|
-
'Never pipe a verify or test command through tail/head/grep
|
|
71
|
+
'Never pipe a verify or test command through tail/head/grep, run it bare and read the real exit code.',
|
|
72
72
|
'Done requires a receipt: paste the exact verify command and its final output lines in your report.',
|
|
73
73
|
'Before deleting or renaming any function or call site, grep the whole repo for its callers; a caller outside your change means the contract stays intact.',
|
|
74
|
-
'Stuck? Never run the same failing command a third time
|
|
74
|
+
'Stuck? Never run the same failing command a third time, write 3 one-line hypotheses, then run the cheapest test that discriminates between them.',
|
|
75
75
|
'Smallest diff that satisfies Done wins; prefer deleting code over adding it.',
|
|
76
76
|
];
|
|
77
77
|
|
|
@@ -99,7 +99,7 @@ function buildFleetPrompt(task, { worktreePath, yolo = false } = {}) {
|
|
|
99
99
|
'',
|
|
100
100
|
ATRIS_BUILD_PROCESS_PREAMBLE,
|
|
101
101
|
'',
|
|
102
|
-
`You are working task ${ref} in this repo checkout (an isolated git worktree${worktreePath ? ` at ${worktreePath}` : ''}
|
|
102
|
+
`You are working task ${ref} in this repo checkout (an isolated git worktree${worktreePath ? ` at ${worktreePath}` : ''}, commit here, NEVER push).`,
|
|
103
103
|
'',
|
|
104
104
|
`Task: ${title}`,
|
|
105
105
|
'',
|
|
@@ -145,10 +145,10 @@ function buildFleetPrompt(task, { worktreePath, yolo = false } = {}) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
// Shell command that runs one engine on one prompt file, from the worktree.
|
|
148
|
-
// Rides the same profile definitions the whole CLI uses
|
|
148
|
+
// Rides the same profile definitions the whole CLI uses, no fleet-only
|
|
149
149
|
// spawn shapes.
|
|
150
150
|
// Build work needs file tools: allowedTools reaches the default claude-shaped
|
|
151
|
-
// spawn; template engines (cursor/codex/devin) ignore it
|
|
151
|
+
// spawn; template engines (cursor/codex/devin) ignore it, their CLIs manage
|
|
152
152
|
// their own permissions.
|
|
153
153
|
const FLEET_ALLOWED_TOOLS = 'Bash,Read,Edit,Write,Grep,Glob';
|
|
154
154
|
const VALIDATOR_ALLOWED_TOOLS = 'Bash,Read,Grep,Glob';
|
|
@@ -864,7 +864,7 @@ function dispatchToEngine({ task, engine, worktreePath, root = process.cwd(), ti
|
|
|
864
864
|
}
|
|
865
865
|
|
|
866
866
|
// ---------------------------------------------------------------------------
|
|
867
|
-
// T2
|
|
867
|
+
// T2: staffing
|
|
868
868
|
|
|
869
869
|
const {
|
|
870
870
|
taskTagTokens,
|
|
@@ -894,7 +894,7 @@ function isSafeLane(task) {
|
|
|
894
894
|
}
|
|
895
895
|
|
|
896
896
|
// Rough file-surface guess from a task's text: paths and bare `commands/x.js`
|
|
897
|
-
// style mentions. Used only to keep concurrent picks disjoint
|
|
897
|
+
// style mentions. Used only to keep concurrent picks disjoint, the merge
|
|
898
898
|
// conflict on 2026-07-02 (two engines in commands/mission.js) is the tax this
|
|
899
899
|
// avoids.
|
|
900
900
|
function fileSurface(task) {
|
|
@@ -938,7 +938,7 @@ function assignEngines(staffed, engines) {
|
|
|
938
938
|
}
|
|
939
939
|
|
|
940
940
|
// ---------------------------------------------------------------------------
|
|
941
|
-
// T3
|
|
941
|
+
// T3: serial landing lane
|
|
942
942
|
|
|
943
943
|
// Land one arrival: rebase onto latest base first; a conflict pauses the
|
|
944
944
|
// landing (never auto-resolve) and reports which files collided so the
|
|
@@ -971,7 +971,7 @@ function dispatchResultToTerminal(entry = {}, result = {}) {
|
|
|
971
971
|
}
|
|
972
972
|
|
|
973
973
|
// Fleet landings always target master. Without the explicit --target, ship
|
|
974
|
-
// falls back to the launcher branch's atris-base
|
|
974
|
+
// falls back to the launcher branch's atris-base, a flight launched from a
|
|
975
975
|
// feature-branch checkout would merge PRs into that branch while the receipt
|
|
976
976
|
// and land board define "landed" as in-master (PRs #207/#208, 2026-07-04).
|
|
977
977
|
// A ship failure must name its real cause. MODULE_NOT_FOUND from the spawned
|
|
@@ -1010,8 +1010,8 @@ function fleetShipArgs(entry, check) {
|
|
|
1010
1010
|
// A fleet build worktree is ephemeral. If any process inside one runs
|
|
1011
1011
|
// `npm link` (which repoints the global `atris` package symlink at that
|
|
1012
1012
|
// worktree), then removing the worktree at teardown leaves the global `atris`
|
|
1013
|
-
// binary a dangling symlink, and everything resolving `atris` through PATH
|
|
1014
|
-
// interactive shells, any tooling that shells out to the bare command
|
|
1013
|
+
// binary a dangling symlink, and everything resolving `atris` through PATH:
|
|
1014
|
+
// interactive shells, any tooling that shells out to the bare command, dies
|
|
1015
1015
|
// with 'command not found'. Measured scope, not assumed: crons that invoke
|
|
1016
1016
|
// `node <checkout>/bin/atris.js` by absolute path are UNAFFECTED; an autoland
|
|
1017
1017
|
// tick ran fine four minutes before the repair. The failure is silent and
|
|
@@ -1083,7 +1083,7 @@ function guardGlobalCliLink({
|
|
|
1083
1083
|
};
|
|
1084
1084
|
}
|
|
1085
1085
|
|
|
1086
|
-
// One-line " (path, path)" suffix naming the files behind a paused landing
|
|
1086
|
+
// One-line " (path, path)" suffix naming the files behind a paused landing,
|
|
1087
1087
|
// unmerged files for a rebase_conflict, uncommitted paths for a dirty_worktree.
|
|
1088
1088
|
function pausedPathsSuffix(landed) {
|
|
1089
1089
|
const paths = (landed && landed.conflicts) || (landed && landed.dirty) || [];
|
|
@@ -1166,10 +1166,10 @@ module.exports = {
|
|
|
1166
1166
|
};
|
|
1167
1167
|
|
|
1168
1168
|
// ---------------------------------------------------------------------------
|
|
1169
|
-
// T4
|
|
1169
|
+
// T4, the conductor: one flight, watchable, receipted
|
|
1170
1170
|
|
|
1171
1171
|
// Engines that can edit a repo headlessly. atris-fast (ax) is a chat lane,
|
|
1172
|
-
// not a repo worker
|
|
1172
|
+
// not a repo worker, it keeps owning normal mission ticks, not fleet builds.
|
|
1173
1173
|
const FLEET_CAPABLE = ['claude', 'codex', 'cursor', 'devin', 'grok'];
|
|
1174
1174
|
const DISPATCH_CAPABLE = [...FLEET_CAPABLE, 'fable', 'commandcode'];
|
|
1175
1175
|
|
|
@@ -2326,6 +2326,33 @@ function defaultOwnCli(root) {
|
|
|
2326
2326
|
};
|
|
2327
2327
|
}
|
|
2328
2328
|
|
|
2329
|
+
// A merge and its task handoff are separate writes. Keep the merge on disk
|
|
2330
|
+
// before attempting the handoff, and never report success if that write fails.
|
|
2331
|
+
function recordLandedTaskReview(cli, args, { flight, landedRow, worktree, save }) {
|
|
2332
|
+
landedRow.review_recorded = false;
|
|
2333
|
+
save();
|
|
2334
|
+
let result;
|
|
2335
|
+
try { result = cli(args); } catch (error) {
|
|
2336
|
+
result = { status: null, stderr: error.message };
|
|
2337
|
+
}
|
|
2338
|
+
if (!result || result.status !== 0) {
|
|
2339
|
+
flight.paused.push({
|
|
2340
|
+
task: landedRow.task,
|
|
2341
|
+
engine: landedRow.engine,
|
|
2342
|
+
stage: 'task_ready',
|
|
2343
|
+
landed: true,
|
|
2344
|
+
worktree,
|
|
2345
|
+
detail: headTail(String(result && (result.stderr || result.stdout) || 'task ready failed')),
|
|
2346
|
+
next_action: 'record fresh task proof with task ready; do not rebuild or merge again',
|
|
2347
|
+
});
|
|
2348
|
+
save();
|
|
2349
|
+
return false;
|
|
2350
|
+
}
|
|
2351
|
+
landedRow.review_recorded = true;
|
|
2352
|
+
save();
|
|
2353
|
+
return true;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2329
2356
|
// Extract a runnable focused check from the task's Check: line; the wide
|
|
2330
2357
|
// gates (npm test, CI) stay at the ship gate, not per-arrival.
|
|
2331
2358
|
function focusedCheck(task) {
|
|
@@ -2539,7 +2566,7 @@ async function runFleetFlight({
|
|
|
2539
2566
|
|
|
2540
2567
|
const staffed = assignEngines(staffedTasks, roster);
|
|
2541
2568
|
// The receipt path is decided BEFORE landings so each task's ready-proof
|
|
2542
|
-
// can cite it
|
|
2569
|
+
// can cite it, the proof policy certifies receipt-backed proofs agent-side.
|
|
2543
2570
|
const receiptPath = path.join(root, 'atris', 'runs', `fleet-${nowStamp()}.json`);
|
|
2544
2571
|
const flight = {
|
|
2545
2572
|
at: new Date().toISOString(),
|
|
@@ -2557,7 +2584,7 @@ async function runFleetFlight({
|
|
|
2557
2584
|
}
|
|
2558
2585
|
|
|
2559
2586
|
log('');
|
|
2560
|
-
log(` fleet
|
|
2587
|
+
log(` fleet, ${roster.length} engine${roster.length === 1 ? '' : 's'} ready, ${staffed.length} task${staffed.length === 1 ? '' : 's'} staffed`);
|
|
2561
2588
|
for (const s of staffed) log(` ${s.engine.padEnd(8)} → ${s.task.display_id} ${String(s.task.title || '').slice(0, 80)}`);
|
|
2562
2589
|
log('');
|
|
2563
2590
|
|
|
@@ -2596,7 +2623,7 @@ async function runFleetFlight({
|
|
|
2596
2623
|
if (!claimed || claimed.status !== 0) {
|
|
2597
2624
|
const detail = String(claimed && (claimed.stderr || claimed.stdout) || 'claim failed').trim().slice(0, 300);
|
|
2598
2625
|
flight.paused.push({ task: entry.task.display_id, engine: entry.engine, stage: 'claim', detail });
|
|
2599
|
-
log(` ${entry.engine.padEnd(8)} ⏸ paused ${entry.task.display_id} at claim${detail ?
|
|
2626
|
+
log(` ${entry.engine.padEnd(8)} ⏸ paused ${entry.task.display_id} at claim${detail ? `, ${detail}` : ''}`);
|
|
2600
2627
|
continue;
|
|
2601
2628
|
}
|
|
2602
2629
|
const started = cli(['worktree', 'start', '--agent', entry.engine, '--task', `fleet-${String(entry.task.display_id).toLowerCase()}`, ...startBaseArgs]);
|
|
@@ -2658,7 +2685,7 @@ async function runFleetFlight({
|
|
|
2658
2685
|
if (result.deadEngine) paused.deadEngine = result.deadEngine;
|
|
2659
2686
|
flight.paused.push(paused);
|
|
2660
2687
|
stampDispatchBrief(root, result.brief_id, 'fail', `build failed for ${entry.task.display_id}`);
|
|
2661
|
-
log(` ${activeEngine.padEnd(8)} ✗ build failed ${entry.task.display_id}
|
|
2688
|
+
log(` ${activeEngine.padEnd(8)} ✗ build failed ${entry.task.display_id}, worktree kept for takeover`);
|
|
2662
2689
|
continue;
|
|
2663
2690
|
}
|
|
2664
2691
|
log(` ${activeEngine.padEnd(8)} landing ${entry.task.display_id}...`);
|
|
@@ -2668,19 +2695,24 @@ async function runFleetFlight({
|
|
|
2668
2695
|
if (result.brief_id) landedRow.brief_id = result.brief_id;
|
|
2669
2696
|
if (result.restaffed) landedRow.restaffed = result.restaffed;
|
|
2670
2697
|
flight.landed.push(landedRow);
|
|
2671
|
-
stampDispatchBrief(root, result.brief_id, 'pass', `landed ${entry.task.display_id} via fleet ship`);
|
|
2672
2698
|
const restaffProof = result.restaffed ? ` Restaffed from ${result.restaffed.from} to ${result.restaffed.to} (${result.restaffed.reason}).` : '';
|
|
2673
|
-
cli
|
|
2699
|
+
const reviewRecorded = recordLandedTaskReview(cli, [
|
|
2674
2700
|
'task', 'ready', String(entry.task.display_id),
|
|
2675
2701
|
'--proof', `Built by ${activeEngine} engine in fleet flight.${restaffProof} Landed via worktree ship gate (rebase-before-ship, verify re-run). Receipt saved at ${path.relative(root, receiptPath)}. Report tail: ${headTail(String(result.report || '').replace(/\n/g, ' '))}`,
|
|
2676
2702
|
'--result', 'Operators can now review fleet-shipped work faster because the worktree was verified before landing.',
|
|
2677
2703
|
'--as', `fleet-${activeEngine}`,
|
|
2678
|
-
]);
|
|
2704
|
+
], { flight, landedRow, worktree: entry.worktreePath, save: () => atomicWriteFlightReceipt(flight, receiptPath) });
|
|
2705
|
+
if (!reviewRecorded) {
|
|
2706
|
+
stampDispatchBrief(root, result.brief_id, 'partial', `landed ${entry.task.display_id}, but task ready failed`);
|
|
2707
|
+
log(' the change landed, but saving its proof failed. repair the task record before starting more work.');
|
|
2708
|
+
continue;
|
|
2709
|
+
}
|
|
2710
|
+
stampDispatchBrief(root, result.brief_id, 'pass', `landed ${entry.task.display_id} via fleet ship`);
|
|
2679
2711
|
log(` ${activeEngine.padEnd(8)} ✓ landed ${entry.task.display_id}`);
|
|
2680
2712
|
} else {
|
|
2681
2713
|
flight.paused.push({ task: entry.task.display_id, engine: activeEngine, ...(result.restaffed ? { restaffed: result.restaffed } : {}), ...landed });
|
|
2682
2714
|
stampDispatchBrief(root, result.brief_id, 'partial', `paused ${entry.task.display_id} at ${landed.stage || 'landing'}`);
|
|
2683
|
-
log(` ${activeEngine.padEnd(8)} ⏸ paused ${entry.task.display_id} at ${landed.stage}${pausedPathsSuffix(landed)}
|
|
2715
|
+
log(` ${activeEngine.padEnd(8)} ⏸ paused ${entry.task.display_id} at ${landed.stage}${pausedPathsSuffix(landed)}, worktree kept`);
|
|
2684
2716
|
}
|
|
2685
2717
|
}
|
|
2686
2718
|
|
|
@@ -2714,7 +2746,7 @@ async function runFleetFlight({
|
|
|
2714
2746
|
}
|
|
2715
2747
|
|
|
2716
2748
|
// ---------------------------------------------------------------------------
|
|
2717
|
-
// T5
|
|
2749
|
+
// T5, one-command dispatch: `atris engine dispatch <task-id> --engine <name>`
|
|
2718
2750
|
|
|
2719
2751
|
// A claim taken before the engine starts must not stay held if the flight
|
|
2720
2752
|
// refuses or errors first. Release through the same task plane the claim used.
|
|
@@ -2736,7 +2768,7 @@ function releaseUnstartedDispatchClaim(cli, { taskId, actor, detail }) {
|
|
|
2736
2768
|
// claim so takeover stays attributed.
|
|
2737
2769
|
function releasePausedClaimsWithoutWork(cli, { paused, worktreeByTask, actorByTask, baseRef = 'origin/master', log = () => {} }) {
|
|
2738
2770
|
for (const row of paused || []) {
|
|
2739
|
-
if (row.stage === 'claim' || row.stage === 'task_lookup') continue; // claim
|
|
2771
|
+
if (row.stage === 'claim' || row.stage === 'task_lookup' || row.landed === true) continue; // no claim, or work already landed
|
|
2740
2772
|
if (row.claim_released !== undefined) continue;
|
|
2741
2773
|
const taskId = String(row.task || '');
|
|
2742
2774
|
const actor = actorByTask.get(taskId);
|
|
@@ -2815,7 +2847,7 @@ async function runDispatchFlight({
|
|
|
2815
2847
|
}
|
|
2816
2848
|
|
|
2817
2849
|
const cli = ownCli || defaultOwnCli(root);
|
|
2818
|
-
// Cut worktrees from
|
|
2850
|
+
// Cut worktrees from, and check self-landing against, the workspace's real
|
|
2819
2851
|
// protected branch, not a hard-coded origin/master (CLI-1298).
|
|
2820
2852
|
const landTarget = resolveDispatchLandTarget(root, checkoutBase);
|
|
2821
2853
|
const verify = verifier || (trustedVerifier ? defaultTrustedVerifyRunner : defaultVerifyRunner);
|
|
@@ -2844,7 +2876,7 @@ async function runDispatchFlight({
|
|
|
2844
2876
|
const liveLogPath = startLiveFlight(root, receiptPath, flight);
|
|
2845
2877
|
|
|
2846
2878
|
log('');
|
|
2847
|
-
log(` dispatch
|
|
2879
|
+
log(` dispatch, ${ids.length} task${ids.length === 1 ? '' : 's'} -> ${engine}`);
|
|
2848
2880
|
log('');
|
|
2849
2881
|
|
|
2850
2882
|
// Same rule as the fleet: dispatch worktrees cut from the protected branch by
|
|
@@ -3100,7 +3132,7 @@ async function runDispatchFlight({
|
|
|
3100
3132
|
if (result.deadEngine) paused.deadEngine = result.deadEngine;
|
|
3101
3133
|
flight.paused.push(paused);
|
|
3102
3134
|
stampDispatchBrief(root, result.brief_id, 'fail', `build failed for ${entry.taskId}`);
|
|
3103
|
-
log(` ✗ build failed ${entry.taskId}
|
|
3135
|
+
log(` ✗ build failed ${entry.taskId}, worktree kept for takeover`);
|
|
3104
3136
|
continue;
|
|
3105
3137
|
}
|
|
3106
3138
|
if (enforceRemoteBoundary && (!candidate || candidate.ok !== true)) {
|
|
@@ -3445,16 +3477,20 @@ async function runDispatchFlight({
|
|
|
3445
3477
|
if (result.brief_id) landedRow.brief_id = result.brief_id;
|
|
3446
3478
|
if (result.restaffed) landedRow.restaffed = result.restaffed;
|
|
3447
3479
|
flight.landed.push(landedRow);
|
|
3448
|
-
|
|
3449
|
-
cli([
|
|
3480
|
+
const reviewRecorded = recordLandedTaskReview(cli, [
|
|
3450
3481
|
'task', 'ready', entry.taskId,
|
|
3451
3482
|
'--proof', `Built by ${activeEngine} engine via atris engine dispatch.${restaffProof} Landed via worktree ship gate (rebase-before-ship, verify re-run). The declared verifier passed (exit 0). Verify output: ${verifyTail || '(command produced no output, exit 0)'}. Receipt saved at ${path.relative(root, receiptPath)}.`,
|
|
3452
3483
|
'--result', 'Operators can now review engine-built work faster because dispatch reran the verifier before landing.',
|
|
3453
|
-
'--landing', 'The verified change is on master and ready for review.',
|
|
3454
3484
|
'--checked', `${landed.check} passed before landing`,
|
|
3455
3485
|
'--tested', 'The requested behavior passed its declared verifier.',
|
|
3456
3486
|
'--as', readyActor,
|
|
3457
|
-
]);
|
|
3487
|
+
], { flight, landedRow, worktree: entry.worktreePath, save: () => writeDispatchReceipt(flight, receiptPath, { ids, reviewOnly, enforceRemoteBoundary }) });
|
|
3488
|
+
if (!reviewRecorded) {
|
|
3489
|
+
stampDispatchBrief(root, result.brief_id, 'partial', `landed ${entry.taskId}, but task ready failed`);
|
|
3490
|
+
log(' the change landed, but saving its proof failed. repair the task record before starting more work.');
|
|
3491
|
+
continue;
|
|
3492
|
+
}
|
|
3493
|
+
stampDispatchBrief(root, result.brief_id, 'pass', `landed ${entry.taskId} via engine dispatch`);
|
|
3458
3494
|
log(` ✓ landed ${entry.taskId}`);
|
|
3459
3495
|
} else {
|
|
3460
3496
|
flight.paused.push({
|
|
@@ -3465,7 +3501,7 @@ async function runDispatchFlight({
|
|
|
3465
3501
|
...landed,
|
|
3466
3502
|
});
|
|
3467
3503
|
stampDispatchBrief(root, result.brief_id, 'partial', `paused ${entry.taskId} at ${landed.stage || 'landing'}`);
|
|
3468
|
-
log(` ⏸ paused ${entry.taskId} at ${landed.stage}${pausedPathsSuffix(landed)}
|
|
3504
|
+
log(` ⏸ paused ${entry.taskId} at ${landed.stage}${pausedPathsSuffix(landed)}, worktree kept`);
|
|
3469
3505
|
}
|
|
3470
3506
|
}
|
|
3471
3507
|
|
package/lib/html-render.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Atris HTML renderer
|
|
1
|
+
// Atris HTML renderer, same content model as the deck engine, rendered to
|
|
2
2
|
// beautiful, anti-slop HTML made of semantic blocks. Pure: spec -> HTML string.
|
|
3
3
|
//
|
|
4
4
|
// Connects with the web apps: the `atris` theme matches atrisos-web tokens
|
package/lib/intents.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const INTENTS = Object.freeze([
|
|
4
|
+
Object.freeze({
|
|
5
|
+
id: 'next_work',
|
|
6
|
+
say: Object.freeze(['what should i do next', 'what is next', 'pick the next thing', 'what do we do now']),
|
|
7
|
+
do: 'atris next',
|
|
8
|
+
plain: 'your agent picks the most useful next step and starts it.',
|
|
9
|
+
offer: 'boot_empty',
|
|
10
|
+
}),
|
|
11
|
+
Object.freeze({
|
|
12
|
+
id: 'keep_going',
|
|
13
|
+
say: Object.freeze(['keep going while i\'m away', 'run overnight', 'finish this', 'keep working without me']),
|
|
14
|
+
do: 'atris spaceship',
|
|
15
|
+
plain: 'your agent keeps working for a few hours and sends updates.',
|
|
16
|
+
offer: 'boot_empty',
|
|
17
|
+
confirm: true,
|
|
18
|
+
}),
|
|
19
|
+
Object.freeze({
|
|
20
|
+
id: 'improve_one_thing',
|
|
21
|
+
say: Object.freeze(['make it better', 'make it faster', 'ship one thing', 'improve this', 'find one useful improvement']),
|
|
22
|
+
do: 'atris improve tick',
|
|
23
|
+
plain: 'your agent finds one useful improvement, makes it, and checks the result.',
|
|
24
|
+
offer: 'after_landing',
|
|
25
|
+
}),
|
|
26
|
+
Object.freeze({
|
|
27
|
+
id: 'clean_up',
|
|
28
|
+
say: Object.freeze(['clean this up', 'it is messy', 'organize this project', 'tidy the loose ends']),
|
|
29
|
+
do: 'atris clean',
|
|
30
|
+
plain: 'your agent finds stale or messy project files and cleans up the safe ones.',
|
|
31
|
+
offer: 'after_landing',
|
|
32
|
+
}),
|
|
33
|
+
Object.freeze({
|
|
34
|
+
id: 'find_or_explain',
|
|
35
|
+
say: Object.freeze(['where is x', 'how does x work', 'where does this live', 'show me where this lives', 'explain this code']),
|
|
36
|
+
do: 'read atris/MAP.md',
|
|
37
|
+
plain: 'your agent reads the project map and points you to the exact files.',
|
|
38
|
+
offer: 'always',
|
|
39
|
+
file: true,
|
|
40
|
+
}),
|
|
41
|
+
Object.freeze({
|
|
42
|
+
id: 'remember_this',
|
|
43
|
+
say: Object.freeze(['remember this', 'save this', 'do not lose this', 'keep this for later']),
|
|
44
|
+
do: 'atris later "<their words>"',
|
|
45
|
+
plain: 'your agent saves this as a note for later.',
|
|
46
|
+
offer: 'always',
|
|
47
|
+
}),
|
|
48
|
+
Object.freeze({
|
|
49
|
+
id: 'schedule_work',
|
|
50
|
+
say: Object.freeze(['every day', 'every morning', 'on a schedule', 'run this regularly']),
|
|
51
|
+
do: 'atris loop',
|
|
52
|
+
plain: 'your agent sets up repeated work on the schedule you describe.',
|
|
53
|
+
offer: 'always',
|
|
54
|
+
confirm: true,
|
|
55
|
+
}),
|
|
56
|
+
Object.freeze({
|
|
57
|
+
id: 'build_an_idea',
|
|
58
|
+
say: Object.freeze(['i want to build x', 'here is an idea', 'can we make x', 'turn this idea into something']),
|
|
59
|
+
do: 'atris wish "<their words>"',
|
|
60
|
+
plain: 'your agent turns the idea into a clear job and starts once any gaps are answered.',
|
|
61
|
+
offer: 'always',
|
|
62
|
+
}),
|
|
63
|
+
Object.freeze({
|
|
64
|
+
id: 'catch_up',
|
|
65
|
+
say: Object.freeze(['catch me up', 'what happened', 'what landed', 'show me recent progress']),
|
|
66
|
+
do: 'atris recap',
|
|
67
|
+
plain: 'your agent summarizes what changed and what still needs attention.',
|
|
68
|
+
offer: 'always',
|
|
69
|
+
}),
|
|
70
|
+
Object.freeze({
|
|
71
|
+
id: 'check_the_work',
|
|
72
|
+
say: Object.freeze(['is this done', 'is it safe', 'check it', 'review this work', 'can i trust this']),
|
|
73
|
+
do: 'atris review',
|
|
74
|
+
plain: 'your agent checks the work, names any risks, and reports whether it is ready.',
|
|
75
|
+
offer: 'after_landing',
|
|
76
|
+
}),
|
|
77
|
+
Object.freeze({
|
|
78
|
+
id: 'use_fewer_credits',
|
|
79
|
+
say: Object.freeze(['use a free model', 'use a cheaper model', 'do not burn credits', 'save credits', 'switch to the fast model']),
|
|
80
|
+
do: 'atris engine atris-fast',
|
|
81
|
+
plain: 'your agent switches this project to the included fast model to spend fewer credits.',
|
|
82
|
+
offer: 'always',
|
|
83
|
+
}),
|
|
84
|
+
Object.freeze({
|
|
85
|
+
id: 'hand_off_work',
|
|
86
|
+
say: Object.freeze(['hand this off', 'have someone else do it', 'delegate this', 'give this to a teammate']),
|
|
87
|
+
do: 'atris task delegate "<their words>" --to <member>',
|
|
88
|
+
plain: 'your agent gives the work to the best available teammate and keeps the handoff visible.',
|
|
89
|
+
offer: 'always',
|
|
90
|
+
confirm: true,
|
|
91
|
+
}),
|
|
92
|
+
Object.freeze({
|
|
93
|
+
id: 'show_or_set_up_team',
|
|
94
|
+
say: Object.freeze(['who owns this', 'set up a team', 'who is responsible', 'show me the team']),
|
|
95
|
+
do: 'atris team',
|
|
96
|
+
plain: 'your agent shows who is responsible and helps fill any missing role.',
|
|
97
|
+
offer: 'always',
|
|
98
|
+
}),
|
|
99
|
+
Object.freeze({
|
|
100
|
+
id: 'speak_plainly',
|
|
101
|
+
say: Object.freeze(['talk plainer', 'too much jargon', 'use plain english', 'keep it simple']),
|
|
102
|
+
do: 'atris clarity --set voice=plain',
|
|
103
|
+
plain: 'your agent saves your preference for short, plain replies.',
|
|
104
|
+
offer: 'always',
|
|
105
|
+
}),
|
|
106
|
+
Object.freeze({
|
|
107
|
+
id: 'set_goal',
|
|
108
|
+
say: Object.freeze(['our goal is x', 'we are trying to x', 'set the goal', 'keep everyone focused on x']),
|
|
109
|
+
do: 'atris goal set "<their words>"',
|
|
110
|
+
plain: 'your agent saves the goal so future work stays pointed at it.',
|
|
111
|
+
offer: 'always',
|
|
112
|
+
}),
|
|
113
|
+
Object.freeze({
|
|
114
|
+
id: 'show_capabilities',
|
|
115
|
+
say: Object.freeze(['what can you do', 'how can you help', 'show me my options', 'what should i ask for']),
|
|
116
|
+
do: 'atris guide',
|
|
117
|
+
plain: 'your agent shows the things it can handle in words you already use.',
|
|
118
|
+
offer: 'always',
|
|
119
|
+
}),
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
const STOP_WORDS = new Set([
|
|
123
|
+
'a', 'an', 'and', 'can', 'could', 'for', 'i', 'im', 'is', 'it', 'me', 'my',
|
|
124
|
+
'of', 'on', 'please', 'the', 'this', 'to', 'we', 'you', 'your',
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
function normalizedTokens(text) {
|
|
128
|
+
const words = String(text || '')
|
|
129
|
+
.toLowerCase()
|
|
130
|
+
.replace(/[\u2018\u2019']/g, '')
|
|
131
|
+
.match(/[a-z0-9]+/g) || [];
|
|
132
|
+
return new Set(words.filter((word) => !STOP_WORDS.has(word)));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function tokenOverlapScore(left, right) {
|
|
136
|
+
if (!left.size || !right.size) return 0;
|
|
137
|
+
let overlap = 0;
|
|
138
|
+
for (const token of left) {
|
|
139
|
+
if (right.has(token)) overlap += 1;
|
|
140
|
+
}
|
|
141
|
+
if (!overlap) return 0;
|
|
142
|
+
return (2 * overlap) / (left.size + right.size);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function intentScore(tokens, intent) {
|
|
146
|
+
return intent.say.reduce((best, phrase) => (
|
|
147
|
+
Math.max(best, tokenOverlapScore(tokens, normalizedTokens(phrase)))
|
|
148
|
+
), 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function matchIntent(text) {
|
|
152
|
+
const tokens = normalizedTokens(text);
|
|
153
|
+
const ranked = INTENTS
|
|
154
|
+
.map((intent, index) => ({ intent, score: intentScore(tokens, intent), index }))
|
|
155
|
+
.sort((left, right) => right.score - left.score || left.index - right.index);
|
|
156
|
+
|
|
157
|
+
// A 0.46 F1 threshold needs about half of the meaningful words to overlap.
|
|
158
|
+
// It catches natural additions such as "please make this faster" while
|
|
159
|
+
// refusing requests that share only one generic word with a phrase.
|
|
160
|
+
const threshold = 0.46;
|
|
161
|
+
if (!ranked.length || ranked[0].score < threshold) {
|
|
162
|
+
return { intent: null, alternatives: ranked.slice(0, 3).map((item) => item.intent) };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
intent: ranked[0].intent,
|
|
167
|
+
score: Number(ranked[0].score.toFixed(3)),
|
|
168
|
+
alternatives: ranked.slice(1, 3).map((item) => item.intent),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = { INTENTS, matchIntent };
|
package/lib/journal.js
CHANGED
|
@@ -84,7 +84,7 @@ function mergeSections(localSections, remoteSections, knownRemoteHash) {
|
|
|
84
84
|
|
|
85
85
|
// Check if the full remote document matches the known state.
|
|
86
86
|
// knownRemoteHash is a hash of the entire document at last sync.
|
|
87
|
-
// If it matches, remote hasn't changed
|
|
87
|
+
// If it matches, remote hasn't changed, prefer all local edits.
|
|
88
88
|
const remoteReconstructed = reconstructJournal(remoteSections);
|
|
89
89
|
const currentRemoteHash = computeContentHash(remoteReconstructed);
|
|
90
90
|
const remoteUnchanged = knownRemoteHash && currentRemoteHash === knownRemoteHash;
|
package/lib/known-commands.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const knownCommands = ['init', 'doctor', 'install', 'workspace', 'log', 'logs', 'later', 'wish', 'ask', 'approve', 'stop', 'ready', 'check', 'drill', 'dream', 'now', 'goal', 'wtf', 'founder', 'orb', 'radar', 'who', 'stream', 'ctop', 'launchpad', 'status', 'analytics', 'revisions', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', 'plan', 'do', 'review', 'release',
|
|
3
|
+
const knownCommands = ['init', 'guide', 'doctor', 'install', 'workspace', 'log', 'logs', 'later', 'wish', 'ask', 'approve', 'stop', 'ready', 'check', 'drill', 'dream', 'now', 'goal', 'wtf', 'founder', 'orb', 'radar', 'who', 'stream', 'ctop', 'launchpad', 'status', 'analytics', 'revisions', 'visualize', 'brain', 'brainstorm', 'autopilot', 'run', 'plan', 'do', 'review', 'release',
|
|
4
4
|
'activate', '_activate', 'agent', 'team', 'chat', 'fast', 'ax', 'console', 'serve', 'login', 'logout', 'whoami', 'switch', 'use', 'accounts', '_resolve', '_profile-email', '_switch-session', 'shell-init', 'update', 'upgrade', 'version', 'help', 'next', 'atris',
|
|
5
|
-
'clean', 'close', 'harvest', 'verify', 'recover', 'search', 'scout', 'skill', 'member', 'codex-goal', 'app', 'apps', 'learn', 'lesson', 'taste', 'teach', 'plugin', 'experiments', 'bench', 'router', 'receipt', 'proof', 'openclaw', 'pull', 'push', 'watch', 'cloud', 'live', 'align', 'terminal', 'computer', 'diff', 'business', 'sync', 'youtube', 'x-search',
|
|
5
|
+
'clean', 'close', 'harvest', 'verify', 'recover', 'search', 'scout', 'skill', 'member', 'codex-goal', 'app', 'apps', 'learn', 'lesson', 'taste', 'teach', 'plugin', 'experiments', 'bench', 'router', 'tree', 'receipt', 'proof', 'openclaw', 'pull', 'push', 'watch', 'cloud', 'live', 'align', 'terminal', 'computer', 'diff', 'business', 'sync', 'youtube', 'x-search',
|
|
6
6
|
'ingest', 'query', 'lint', 'loop', 'pulse', 'task', 'mission', 'decide', 'agents', 'probe', 'worktree', 'land', 'caretaker', 'autoland', 'drive', 'aeo', 'slop', 'voice', 'strings', 'write', 'security-review', 'secure', 'deck', 'site', 'theme', 'card', 'reel', 'improve', 'study', 'rainmaker', 'xp', 'play', 'gm', 'game', 'x', 'recap', 'report', 'signup', 'clarity', 'interview', 'meet', 'moves', 'unknowns', 'avail', 'sync-checkout',
|
|
7
7
|
'ci', 'github', 'vercel', 'supabase', 'linear', 'stripe', 'balance', 'usage', 'api-key', 'topup', 'gmail', 'calendar', 'twitter', 'slack', 'imessage', 'integrations', 'setup', 'clean-workspace', 'cw',
|
|
8
8
|
'fork', 'browse', 'publish', 'pack', 'sleep', 'wake', 'feedback', 'errors', 'wiki', 'code-review', 'cr', 'soul', 'fleet', 'fleet-report', 'loops', 'self-improve', 'compile', 'spaceship', 'truth', 'sign', 'engine', 'engines', 'playbook', 'feed', 'brief', 'social', 'people', 'follow', 'unfollow', 'friends', 'msg', 'inbox', 'invite', 'join'];
|