atris 3.52.0 → 3.55.0

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 (131) hide show
  1. package/FOR_AGENTS.md +7 -0
  2. package/README.md +1 -1
  3. package/atris/policies/ANTISLOP.md +2 -1
  4. package/atris/skills/copy-editor/SKILL.md +2 -1
  5. package/atris/skills/design/SKILL.md +1 -1
  6. package/atris/skills/engines/SKILL.md +8 -7
  7. package/atris/skills/x-search/SKILL.md +24 -22
  8. package/atris/skills/youtube/SKILL.md +89 -40
  9. package/atris/team/_template/SOUL.md +40 -0
  10. package/atris/team/validator/MEMBER.md +1 -2
  11. package/ax +592 -91
  12. package/bin/atris +21 -0
  13. package/bin/atris.js +580 -378
  14. package/commands/api-key.js +170 -0
  15. package/commands/auth.js +453 -43
  16. package/commands/autoland.js +3 -1
  17. package/commands/autopilot-front.js +58 -11
  18. package/commands/avail.js +5 -4
  19. package/commands/balance.js +55 -0
  20. package/commands/bench.js +29 -1
  21. package/commands/brain.js +63 -12
  22. package/commands/brainstorm.js +18 -0
  23. package/commands/business.js +149 -1
  24. package/commands/chat-scan.js +17 -4
  25. package/commands/close.js +5 -1
  26. package/commands/computer.js +2 -2
  27. package/commands/doctor.js +174 -0
  28. package/commands/dream.js +7 -0
  29. package/commands/drill.js +34 -2
  30. package/commands/engine.js +47 -35
  31. package/commands/errors.js +58 -8
  32. package/commands/experiments.js +14 -0
  33. package/commands/feedback.js +61 -2
  34. package/commands/fleet-report.js +27 -7
  35. package/commands/fleet.js +98 -11
  36. package/commands/founder.js +60 -21
  37. package/commands/human-missions.js +79 -4
  38. package/commands/improve.js +54 -4
  39. package/commands/init.js +68 -92
  40. package/commands/install.js +40 -0
  41. package/commands/integrations.js +399 -30
  42. package/commands/interview.js +8 -0
  43. package/commands/land.js +48 -17
  44. package/commands/learn.js +29 -4
  45. package/commands/log.js +51 -0
  46. package/commands/member.js +68 -10
  47. package/commands/mission.js +339 -74
  48. package/commands/now.js +25 -6
  49. package/commands/orb.js +97 -2
  50. package/commands/pack.js +83 -9
  51. package/commands/playbook.js +381 -0
  52. package/commands/plugin.js +16 -0
  53. package/commands/radar.js +96 -40
  54. package/commands/recap.js +128 -21
  55. package/commands/release.js +102 -2
  56. package/commands/review.js +5 -10
  57. package/commands/revisions.js +55 -0
  58. package/commands/run-front.js +12 -4
  59. package/commands/scout.js +12 -1
  60. package/commands/search.js +123 -28
  61. package/commands/sign.js +2 -2
  62. package/commands/signup.js +12 -3
  63. package/commands/site-deploy.js +17 -4
  64. package/commands/site.js +2 -2
  65. package/commands/skill-eval.js +289 -0
  66. package/commands/skill.js +56 -6
  67. package/commands/social.js +603 -0
  68. package/commands/spaceship.js +69 -6
  69. package/commands/stream.js +8 -1
  70. package/commands/study.js +32 -19
  71. package/commands/sync.js +28 -22
  72. package/commands/task.js +418 -60
  73. package/commands/teach.js +72 -63
  74. package/commands/terminal.js +25 -9
  75. package/commands/topup.js +88 -0
  76. package/commands/truth.js +52 -6
  77. package/commands/usage.js +91 -0
  78. package/commands/verify.js +3 -2
  79. package/commands/version.js +3 -1
  80. package/commands/voice.js +5 -1
  81. package/commands/who.js +69 -11
  82. package/commands/wiki.js +7 -4
  83. package/commands/wish.js +76 -5
  84. package/commands/workflow.js +327 -145
  85. package/commands/worktree.js +1 -0
  86. package/commands/write.js +5 -0
  87. package/commands/x-search.js +340 -0
  88. package/commands/xp.js +5 -1
  89. package/commands/youtube.js +551 -33
  90. package/lib/account-bound.js +47 -0
  91. package/lib/auto-accept-certified.js +10 -2
  92. package/lib/auto-lessons.js +186 -0
  93. package/lib/autoland.js +4 -2
  94. package/lib/chat-log-scan.js +7 -4
  95. package/lib/cli-json.js +77 -0
  96. package/lib/cli-scope.js +26 -0
  97. package/lib/codex-flight.js +1 -0
  98. package/lib/conductor-artifacts.js +1 -1
  99. package/lib/context-gatherer.js +11 -0
  100. package/lib/developer-api.js +116 -0
  101. package/lib/engine-ask.js +11 -3
  102. package/lib/engine-registry.js +32 -7
  103. package/lib/feedback-triage.js +274 -0
  104. package/lib/first-minute.js +398 -0
  105. package/lib/fleet.js +115 -34
  106. package/lib/functional-owner.js +22 -0
  107. package/lib/known-commands.js +31 -5
  108. package/lib/member-scaffold.js +197 -0
  109. package/lib/mission-ledger-compact.js +127 -0
  110. package/lib/mission-root.js +4 -2
  111. package/lib/mission-runtime-loop.js +30 -2
  112. package/lib/next-moves.js +34 -34
  113. package/lib/noninteractive.js +88 -0
  114. package/lib/permission-grants.js +10 -1
  115. package/lib/policy-lessons.js +4 -1
  116. package/lib/revision-metric.js +279 -0
  117. package/lib/runner-command.js +5 -4
  118. package/lib/scratch-root.js +48 -0
  119. package/lib/skill-eval-gate.js +249 -0
  120. package/lib/task-db.js +22 -2
  121. package/lib/task-proof.js +75 -9
  122. package/lib/task-receipt.js +5 -1
  123. package/lib/verifier-quality.js +69 -0
  124. package/lib/wish-audit.js +2 -2
  125. package/lib/wish-delegate.js +10 -1
  126. package/lib/workspace-scaffold.js +270 -0
  127. package/package.json +4 -2
  128. package/scripts/det/checklist-score.js +191 -0
  129. package/scripts/det/ytsearch +31 -0
  130. package/scripts/outbound-artifact-gate.js +227 -0
  131. package/utils/update-check.js +15 -0
package/commands/land.js CHANGED
@@ -19,6 +19,10 @@ function repoRoot(cwd = process.cwd()) {
19
19
  return result.stdout.trim();
20
20
  }
21
21
 
22
+ function hasCommits(root) {
23
+ return runGit(['rev-parse', '--verify', '--quiet', 'HEAD'], { cwd: root, check: false }).status === 0;
24
+ }
25
+
22
26
  function refExists(root, ref) {
23
27
  return runGit(['rev-parse', '--verify', '--quiet', ref], { cwd: root, check: false }).status === 0;
24
28
  }
@@ -111,7 +115,11 @@ function cherryStats(root, base, ref) {
111
115
  // due — has unlanded commits, older than TTL; --reap collects it
112
116
  function collectBoard(root, { ttlDays = DEFAULT_TTL_DAYS, staleHours = DEFAULT_STALE_HOURS, base: baseOverride = '', now = Date.now(), light = false } = {}) {
113
117
  const base = baseBranch(root, baseOverride);
114
- if (!base) throw new Error('no master/main branch found');
118
+ if (!base) {
119
+ const err = new Error('no master/main branch found. fix: git checkout -b main');
120
+ err.code = 'LAND_NO_BASE';
121
+ throw err;
122
+ }
115
123
 
116
124
  const branches = [];
117
125
  const lastCommitMsByBranch = new Map();
@@ -457,7 +465,11 @@ function reap(root, { ttlDays = DEFAULT_TTL_DAYS, staleHours = DEFAULT_STALE_HOU
457
465
  // into master some other way, and what would be lost if it were cleared.
458
466
  function collectStory(root, name, { base: baseOverride = '' } = {}) {
459
467
  const base = baseBranch(root, baseOverride);
460
- if (!base) throw new Error('no master/main branch found');
468
+ if (!base) {
469
+ const err = new Error('no master/main branch found. fix: git checkout -b main');
470
+ err.code = 'LAND_NO_BASE';
471
+ throw err;
472
+ }
461
473
  if (!refExists(root, name)) return null;
462
474
 
463
475
  const logResult = runGit(
@@ -656,7 +668,11 @@ function landCommand(args = []) {
656
668
  }
657
669
  const root = repoRoot();
658
670
  if (!root) {
659
- console.error('not a git repository');
671
+ console.error('not a git repository. fix: git init -b main');
672
+ return 1;
673
+ }
674
+ if (!hasCommits(root)) {
675
+ console.error('no commits yet. fix: git commit --allow-empty -m init');
660
676
  return 1;
661
677
  }
662
678
  const ttlRaw = readFollowingFlag(args, '--ttl', '');
@@ -666,29 +682,44 @@ function landCommand(args = []) {
666
682
  const json = args.includes('--json');
667
683
 
668
684
  if (args.includes('--reap')) {
669
- const receipt = reap(root, { ttlDays, base, dryRun: args.includes('--dry-run'), remote: !args.includes('--no-remote'), force: args.includes('--force') });
670
- if (json) console.log(JSON.stringify(receipt, null, 2));
671
- else printReceipt(receipt);
672
- return 0;
685
+ try {
686
+ const receipt = reap(root, { ttlDays, base, dryRun: args.includes('--dry-run'), remote: !args.includes('--no-remote'), force: args.includes('--force') });
687
+ if (json) console.log(JSON.stringify(receipt, null, 2));
688
+ else printReceipt(receipt);
689
+ return 0;
690
+ } catch (err) {
691
+ console.error(String(err && err.message || err));
692
+ return 1;
693
+ }
673
694
  }
674
695
 
675
696
  const lookupArgs = args[0] === 'status' ? args.slice(1) : args;
676
697
  const name = lookupArgs.find((a) => !a.startsWith('-') && a !== readFollowingFlag(lookupArgs, '--ttl') && a !== readFollowingFlag(lookupArgs, '--base'));
677
698
  if (name) {
678
- const story = collectStory(root, name, { base });
679
- if (!story) {
680
- console.error(`nothing called '${name}' is in the air right now`);
699
+ try {
700
+ const story = collectStory(root, name, { base });
701
+ if (!story) {
702
+ console.error(`nothing called '${name}' is in the air right now`);
703
+ return 1;
704
+ }
705
+ if (json) console.log(JSON.stringify(story, null, 2));
706
+ else printStory(story);
707
+ return 0;
708
+ } catch (err) {
709
+ console.error(String(err && err.message || err));
681
710
  return 1;
682
711
  }
683
- if (json) console.log(JSON.stringify(story, null, 2));
684
- else printStory(story);
685
- return 0;
686
712
  }
687
713
 
688
- const board = collectBoard(root, { ttlDays, base });
689
- if (json) console.log(JSON.stringify(board, null, 2));
690
- else printBoard(board);
691
- return 0;
714
+ try {
715
+ const board = collectBoard(root, { ttlDays, base });
716
+ if (json) console.log(JSON.stringify(board, null, 2));
717
+ else printBoard(board);
718
+ return 0;
719
+ } catch (err) {
720
+ console.error(String(err && err.message || err));
721
+ return 1;
722
+ }
692
723
  }
693
724
 
694
725
  module.exports = {
package/commands/learn.js CHANGED
@@ -227,21 +227,42 @@ function interactiveAdd() {
227
227
  })();
228
228
  }
229
229
 
230
+ function learnLogSchemaLines() {
231
+ return [
232
+ 'Schema: {"type":"pattern|pitfall|preference|architecture|tool","key":"...","insight":"...","confidence":1-10,"source":"observed|user-stated|inferred|review"}',
233
+ 'Required: type, key, insight. Aliases: title→key, detail→insight. Optional: confidence (default 5), source (default observed), files[].',
234
+ 'Example: atris learn log \'{"type":"pattern","title":"map-first","detail":"check MAP.md before grep","confidence":8}\'',
235
+ ];
236
+ }
237
+
238
+ function printLearnLogSchema(stream = console.error) {
239
+ for (const line of learnLogSchemaLines()) stream(` ${line}`);
240
+ }
241
+
230
242
  /**
231
243
  * Non-interactive log: `atris learn log '{"type":"pattern","key":"...","insight":"...","confidence":8,"source":"observed"}'`
232
244
  * For agents and scripts — no prompts, no quality gate.
245
+ * Aliases: title→key, detail→insight.
233
246
  */
234
247
  function logDirect(jsonStr) {
235
248
  if (!jsonStr) {
236
- console.error(' ✗ Usage: atris learn log \'{"type":"...","key":"...","insight":"...","confidence":N,"source":"..."}\'');
249
+ console.error(' ✗ Usage: atris learn log \'<json>\'');
250
+ printLearnLogSchema();
251
+ process.exit(1);
252
+ }
253
+ let data;
254
+ try {
255
+ data = JSON.parse(jsonStr);
256
+ } catch (err) {
257
+ console.error(` ✗ Invalid JSON: ${err.message}`);
258
+ printLearnLogSchema();
237
259
  process.exit(1);
238
260
  }
239
261
  try {
240
- const data = JSON.parse(jsonStr);
241
262
  const entry = addLearning({
242
263
  type: data.type,
243
- key: data.key,
244
- insight: data.insight,
264
+ key: data.key || data.title,
265
+ insight: data.insight || data.detail,
245
266
  confidence: data.confidence || 5,
246
267
  source: data.source || 'observed',
247
268
  files: data.files || [],
@@ -249,6 +270,7 @@ function logDirect(jsonStr) {
249
270
  console.log(` ✓ [${entry.confidence}/10] ${entry.type}/${entry.key}`);
250
271
  } catch (err) {
251
272
  console.error(` ✗ ${err.message}`);
273
+ printLearnLogSchema();
252
274
  process.exit(1);
253
275
  }
254
276
  }
@@ -362,6 +384,9 @@ function showLearnHelp() {
362
384
  console.log(' export Export as markdown');
363
385
  console.log(' count Print learning count (for integrations)');
364
386
  console.log('');
387
+ console.log(' learn log schema:');
388
+ for (const line of learnLogSchemaLines()) console.log(` ${line}`);
389
+ console.log('');
365
390
  }
366
391
 
367
392
  function learnAtris(subcommand, ...args) {
package/commands/log.js CHANGED
@@ -2,6 +2,15 @@ const fs = require('fs');
2
2
  const path = require('path');
3
3
  const readline = require('readline');
4
4
  const { getLogPath, ensureLogDirectory, createLogFile, addInboxIdea } = require('../lib/file-ops');
5
+ const { isForcedNonInteractive } = require('../lib/noninteractive');
6
+
7
+ function readPipedStdin() {
8
+ try {
9
+ return fs.readFileSync(0, 'utf8');
10
+ } catch {
11
+ return '';
12
+ }
13
+ }
5
14
 
6
15
  function logAtris() {
7
16
  const targetDir = path.join(process.cwd(), 'atris');
@@ -18,6 +27,48 @@ function logAtris() {
18
27
  createLogFile(logFile, dateFormatted);
19
28
  }
20
29
 
30
+ const args = process.argv.slice(3);
31
+ const rel = path.relative(process.cwd(), logFile) || logFile;
32
+ const forced = isForcedNonInteractive(args);
33
+ const wantsRepl = args.includes('--repl');
34
+ const positional = args.filter((arg) => !String(arg).startsWith('-'));
35
+ const note = positional.join(' ').trim();
36
+
37
+ // `atris log "sentence"` (or multi-word args) appends to today's Inbox.
38
+ if (note && !wantsRepl) {
39
+ const id = addInboxIdea(logFile, note);
40
+ console.log(`captured I${id}: ${note}`);
41
+ console.log(`journal: ${rel}`);
42
+ console.log('Next: atris logs');
43
+ return;
44
+ }
45
+
46
+ // Forced headless: never open a REPL.
47
+ if (forced) {
48
+ console.log(`Daily log REPL needs a terminal (${dateFormatted}).`);
49
+ console.log(`journal: ${rel}`);
50
+ console.log('Next: atris log --repl # in a terminal, or atris log "note" / atris wish --json --no-mission');
51
+ return;
52
+ }
53
+
54
+ // Piped stdin (tests and scripts): consume lines once, never hang waiting.
55
+ if (!process.stdin.isTTY) {
56
+ const piped = readPipedStdin();
57
+ const lines = piped.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
58
+ const notes = lines.filter((line) => line.toLowerCase() !== 'exit');
59
+ if (notes.length === 0) {
60
+ console.log(`Daily log REPL needs a terminal (${dateFormatted}).`);
61
+ console.log(`journal: ${rel}`);
62
+ console.log('Next: atris log --repl # in a terminal, or atris log "note" / atris logs --json');
63
+ return;
64
+ }
65
+ for (const noteLine of notes) {
66
+ addInboxIdea(logFile, noteLine);
67
+ }
68
+ console.log(`captured ${notes.length} note${notes.length === 1 ? '' : 's'} in ${rel}`);
69
+ return;
70
+ }
71
+
21
72
  console.log(`┌─────────────────────────────────────────────────────────┐`);
22
73
  console.log(`│ Daily Log — ${dateFormatted} [type "exit" to quit] │`);
23
74
  console.log(`└─────────────────────────────────────────────────────────┘`);
@@ -9,6 +9,7 @@ const { runAliveTick } = require('../lib/member-alive');
9
9
  const { defaultObjectiveRunner } = require('../lib/default-runner');
10
10
  const { readJson, writeJson } = require('../lib/json-file');
11
11
  const { hasFlag, readFlag, readNumberFlag } = require('../lib/arg-parser');
12
+ const { ensureMemberBundle, memberBundlePresent } = require('../lib/member-scaffold');
12
13
 
13
14
  function findWorkspaceBusinessId(startDir = process.cwd()) {
14
15
  let dir = path.resolve(startDir);
@@ -113,7 +114,7 @@ function readRepeatedFlag(args, name) {
113
114
  function stripKnownFlags(args, valueNames, booleanNames = []) {
114
115
  const out = [];
115
116
  const valueSet = new Set(valueNames);
116
- const booleanSet = new Set(booleanNames);
117
+ const booleanSet = new Set(['--full', '--verbose', ...booleanNames]);
117
118
  for (let i = 0; i < args.length; i += 1) {
118
119
  const arg = String(args[i]);
119
120
  const key = arg.includes('=') ? arg.slice(0, arg.indexOf('=')) : arg;
@@ -3933,10 +3934,27 @@ function findAllMembers(teamDir) {
3933
3934
 
3934
3935
  // --- LIST subcommand ---
3935
3936
 
3936
- function memberList() {
3937
+ function memberList(...flags) {
3938
+ const asJson = flags.includes('--json') || process.argv.includes('--json');
3937
3939
  const teamDir = path.join(process.cwd(), 'atris', 'team');
3938
3940
  const members = findAllMembers(teamDir);
3939
3941
 
3942
+ if (asJson) {
3943
+ console.log(JSON.stringify({
3944
+ ok: true,
3945
+ count: members.length,
3946
+ members: members.map((m) => ({
3947
+ name: m.name,
3948
+ role: m.role,
3949
+ format: m.format,
3950
+ skills: m.format === 'directory' ? m.skillCount : null,
3951
+ context: m.format === 'directory' ? m.contextCount : null,
3952
+ version: m.version || null,
3953
+ })),
3954
+ }, null, 2));
3955
+ return;
3956
+ }
3957
+
3940
3958
  if (members.length === 0) {
3941
3959
  console.log('No team members found in atris/team/.');
3942
3960
  console.log('Run "atris member create <name>" to create one.');
@@ -3969,11 +3987,11 @@ function memberList() {
3969
3987
  const context = m.format === 'directory' ? String(m.contextCount) : '-';
3970
3988
  console.log(
3971
3989
  ' ' +
3972
- m.name.padEnd(nameW) +
3973
- m.role.substring(0, roleW - 1).padEnd(roleW) +
3974
- (m.format === 'directory' ? 'dir' : 'flat').padEnd(fmtW) +
3975
- skills.padEnd(skillW) +
3976
- context.padEnd(ctxW) +
3990
+ clipCell(m.name, nameW) +
3991
+ clipCell(m.role, roleW) +
3992
+ clipCell(m.format === 'directory' ? 'dir' : 'flat', fmtW) +
3993
+ clipCell(skills, skillW) +
3994
+ clipCell(context, ctxW) +
3977
3995
  (m.version || '-')
3978
3996
  );
3979
3997
  }
@@ -4119,6 +4137,42 @@ tools: []
4119
4137
  }
4120
4138
  }
4121
4139
 
4140
+ function printMemberInstallUsage(stream = console.log) {
4141
+ stream('Usage: atris member install <slug>');
4142
+ }
4143
+
4144
+ function memberInstall(slug) {
4145
+ if (slug === '--help' || slug === '-h') {
4146
+ printMemberInstallUsage();
4147
+ return;
4148
+ }
4149
+ if (!slug || String(slug).startsWith('-')) {
4150
+ printMemberInstallUsage(console.error);
4151
+ process.exit(1);
4152
+ }
4153
+ if (!/^[a-zA-Z0-9._-]+$/.test(slug)) {
4154
+ console.error('Member name must be a local slug: letters, numbers, dots, underscores, or dashes.');
4155
+ process.exit(1);
4156
+ }
4157
+
4158
+ const memberDir = path.join(process.cwd(), 'atris', 'team', slug);
4159
+ const already = memberBundlePresent(memberDir);
4160
+ fs.mkdirSync(path.join(memberDir, 'logs'), { recursive: true });
4161
+ if (already) {
4162
+ console.log(`MEMBER already installed for ${slug}`);
4163
+ return;
4164
+ }
4165
+
4166
+ const { created } = ensureMemberBundle(memberDir, {
4167
+ name: slug,
4168
+ source: 'install',
4169
+ });
4170
+ for (const rel of created) {
4171
+ console.log(`atris/team/${slug}/${rel.split(path.sep).join('/')}`);
4172
+ }
4173
+ console.log(`MEMBER installed for ${slug}.`);
4174
+ }
4175
+
4122
4176
  // --- ACTIVATE subcommand ---
4123
4177
 
4124
4178
  function memberActivate(name) {
@@ -9010,17 +9064,19 @@ async function memberCommand(subcommand, ...args) {
9010
9064
  // Subcommands that take a member name as args[0] otherwise treat `--help` as
9011
9065
  // a name and error with "Member '--help' not found". `create`/`new` handle
9012
9066
  // help themselves (with subcommand-specific usage) — leave those alone.
9013
- const HELP_AWARE_SUBCOMMANDS = new Set(['create', 'new', 'run']);
9067
+ const HELP_AWARE_SUBCOMMANDS = new Set(['create', 'new', 'run', 'install']);
9014
9068
  if (!HELP_AWARE_SUBCOMMANDS.has(subcommand) && (args[0] === '-h' || args[0] === '--help')) {
9015
9069
  subcommand = undefined;
9016
9070
  }
9017
9071
  switch (subcommand) {
9018
9072
  case 'list':
9019
9073
  case 'ls':
9020
- return memberList();
9074
+ return memberList(...args);
9021
9075
  case 'create':
9022
9076
  case 'new':
9023
9077
  return memberCreate(args[0], ...args.slice(1));
9078
+ case 'install':
9079
+ return memberInstall(args[0]);
9024
9080
  case 'activate':
9025
9081
  return memberActivate(args[0]);
9026
9082
  case 'upgrade':
@@ -9082,8 +9138,9 @@ async function memberCommand(subcommand, ...args) {
9082
9138
  console.log('');
9083
9139
  console.log('Subcommands:');
9084
9140
  console.log(' create <name> Scaffold a new team member (MEMBER.md + dirs) [--push]');
9141
+ console.log(' install <slug> Install the full MEMBER bundle if missing; never overwrite');
9085
9142
  console.log(' chat <name> "..." Send a message to this member\'s desk in Atris Desktop');
9086
- console.log(' list Show all team members');
9143
+ console.log(' list [--json] Show all team members');
9087
9144
  console.log(' activate <name> Symlink member skills, show context and permissions');
9088
9145
  console.log(' upgrade <name> Convert flat file (name.md) to directory format');
9089
9146
  console.log(' push <name> Push a local team member to the cloud');
@@ -9116,6 +9173,7 @@ async function memberCommand(subcommand, ...args) {
9116
9173
  console.log('');
9117
9174
  console.log('Examples:');
9118
9175
  console.log(' atris member create sdr --role="Sales Development Rep"');
9176
+ console.log(' atris member install orb');
9119
9177
  console.log(' atris member list');
9120
9178
  console.log(' atris member activate navigator');
9121
9179
  console.log(' atris member upgrade executor');