atris 3.37.0 → 3.38.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 (139) hide show
  1. package/README.md +2 -0
  2. package/atris/PERSONA.md +3 -7
  3. package/atris.md +10 -2
  4. package/ax +158 -33
  5. package/bin/atris.js +49 -2
  6. package/commands/activate.js +16 -3
  7. package/commands/agent-spawn.js +0 -7
  8. package/commands/autoland.js +92 -14
  9. package/commands/autopilot-front.js +0 -4
  10. package/commands/autopilot.js +0 -12
  11. package/commands/brain.js +0 -7
  12. package/commands/brief.js +0 -2
  13. package/commands/business-sync.js +0 -1
  14. package/commands/business.js +107 -12
  15. package/commands/clean.js +31 -2
  16. package/commands/close.js +46 -11
  17. package/commands/cloud.js +0 -1
  18. package/commands/codex-goal.js +0 -2
  19. package/commands/computer.js +6 -5
  20. package/commands/console.js +46 -9
  21. package/commands/deck.js +29 -8
  22. package/commands/dream.js +0 -7
  23. package/commands/drill.js +0 -1
  24. package/commands/engine.js +10 -18
  25. package/commands/experiments.js +0 -4
  26. package/commands/fleet-report.js +12 -4
  27. package/commands/game.js +261 -0
  28. package/commands/gm.js +10 -2
  29. package/commands/goal.js +0 -6
  30. package/commands/harvest.js +0 -1
  31. package/commands/improve.js +29 -8
  32. package/commands/init.js +18 -34
  33. package/commands/integrations.js +0 -7
  34. package/commands/land.js +71 -8
  35. package/commands/launchpad.js +0 -2
  36. package/commands/lesson.js +17 -7
  37. package/commands/loop-front.js +0 -2
  38. package/commands/loops.js +6 -5
  39. package/commands/meet.js +0 -2
  40. package/commands/member.js +68 -3
  41. package/commands/mission.js +359 -102
  42. package/commands/next.js +0 -1
  43. package/commands/now.js +0 -12
  44. package/commands/one-lap.js +8 -8
  45. package/commands/orb.js +0 -4
  46. package/commands/pack-craft.js +0 -1
  47. package/commands/pack.js +670 -77
  48. package/commands/play.js +0 -2
  49. package/commands/probe.js +10 -4
  50. package/commands/pulse.js +73 -48
  51. package/commands/push.js +0 -4
  52. package/commands/radar.js +14 -11
  53. package/commands/recover.js +340 -0
  54. package/commands/report.js +0 -1
  55. package/commands/router.js +319 -0
  56. package/commands/run-front.js +0 -2
  57. package/commands/search.js +0 -3
  58. package/commands/skill.js +7 -2
  59. package/commands/slop.js +225 -7
  60. package/commands/status.js +6 -0
  61. package/commands/stream.js +0 -2
  62. package/commands/study.js +0 -3
  63. package/commands/sync-checkout.js +51 -0
  64. package/commands/sync.js +11 -40
  65. package/commands/task.js +125 -39
  66. package/commands/teach.js +86 -0
  67. package/commands/unknowns.js +0 -10
  68. package/commands/update.js +0 -1
  69. package/commands/visualize.js +0 -5
  70. package/commands/watch.js +0 -6
  71. package/commands/wiki.js +41 -11
  72. package/commands/wish.js +0 -1
  73. package/commands/worktree.js +87 -14
  74. package/commands/xp.js +1 -6
  75. package/commands/youtube.js +0 -2
  76. package/lib/accept-verify-gate.js +122 -0
  77. package/lib/activity-stream.js +0 -2
  78. package/lib/auto-accept-certified.js +145 -2
  79. package/lib/autoland.js +0 -3
  80. package/lib/ax-auto-lane.js +94 -10
  81. package/lib/bench/context.js +0 -2
  82. package/lib/bench/report.js +0 -1
  83. package/lib/bench/runner.js +0 -11
  84. package/lib/brief-ledger.js +0 -6
  85. package/lib/business-simulate.js +382 -0
  86. package/lib/chat-log-scan.js +0 -5
  87. package/lib/checkout-sync.js +52 -0
  88. package/lib/claude-boot-block.js +48 -0
  89. package/lib/cloud-mission.js +0 -6
  90. package/lib/codex-flight.js +0 -1
  91. package/lib/conductor-artifacts.js +25 -0
  92. package/lib/context-gatherer.js +0 -1
  93. package/lib/deck-compose.js +0 -1
  94. package/lib/deck-history.js +0 -1
  95. package/lib/deck-layout.js +0 -5
  96. package/lib/deck-review.js +0 -7
  97. package/lib/deck-schema.js +0 -1
  98. package/lib/default-verifier.js +0 -2
  99. package/lib/engine-registry.js +16 -8
  100. package/lib/experiments/daily.js +0 -6
  101. package/lib/fleet.js +210 -27
  102. package/lib/functional-owner.js +0 -3
  103. package/lib/inspect-fields.js +0 -1
  104. package/lib/known-commands.js +2 -2
  105. package/lib/learnings.js +0 -2
  106. package/lib/loop-doctor.js +11 -17
  107. package/lib/manifest.js +0 -2
  108. package/lib/member-alive.js +0 -1
  109. package/lib/member-switches.js +0 -5
  110. package/lib/mission-artifact.js +0 -1
  111. package/lib/mission-protected-lane.js +293 -0
  112. package/lib/mission-room.js +0 -2
  113. package/lib/mission-runtime-loop.js +0 -1
  114. package/lib/next-moves.js +0 -18
  115. package/lib/official-cli-integration.js +0 -4
  116. package/lib/orb-context.js +6 -3
  117. package/lib/orb-scorecard.js +0 -1
  118. package/lib/outbound-send-gate.js +0 -6
  119. package/lib/permission-grants.js +0 -6
  120. package/lib/policy-lessons.js +0 -2
  121. package/lib/pulse.js +68 -15
  122. package/lib/review-integrity.js +0 -2
  123. package/lib/router-brain.js +0 -2
  124. package/lib/runner-command.js +0 -4
  125. package/lib/runtime-bootstrap.js +0 -1
  126. package/lib/scorecard.js +0 -1
  127. package/lib/self-drive.js +1 -1
  128. package/lib/state-detection.js +0 -6
  129. package/lib/task-db.js +0 -4
  130. package/lib/team-presence.js +0 -1
  131. package/lib/voice-gate.js +63 -2
  132. package/lib/wiki.js +152 -9
  133. package/lib/wish-audit.js +20 -6
  134. package/lib/wish-delegate.js +26 -20
  135. package/lib/wish-stats.js +0 -5
  136. package/lib/wish-store.js +0 -1
  137. package/lib/workspace-safety.js +0 -2
  138. package/lib/zip.js +0 -1
  139. package/package.json +1 -1
package/commands/task.js CHANGED
@@ -17,6 +17,7 @@ const {
17
17
  runVerifyCommandCached,
18
18
  DENIED_TAGS,
19
19
  } = require('../lib/auto-accept-certified');
20
+ const { evaluateAcceptVerify } = require('../lib/accept-verify-gate');
20
21
  const { extractReceiptEvidence, RECEIPT_PATH_PATTERN } = require('../lib/receipt-evidence');
21
22
  const escapeRegExp = require('../lib/escape-regexp');
22
23
  const reviewIntegrity = require('../lib/review-integrity');
@@ -880,10 +881,15 @@ function certifiedReviewNextAction(nextTaskTitle) {
880
881
  function proofBoundaryBlockedEvaluation(task) {
881
882
  const missionXpBoundary = missionXpProofBoundaryEvaluation(task);
882
883
  if (missionXpBoundary) return missionXpBoundary;
883
- // strictVerify stays off here: this is a render-path probe for the boundary
884
- // reason only, and the default-true strict mode would spawn the verify
885
- // subprocess for every certified row just to draw the desk.
886
- const evaluation = evaluateAutoAccept(task, { strictVerify: false, minPasses: 0 });
884
+ // This is a render-path probe for the boundary reason only. strictVerify
885
+ // alone is not enough to keep it read-only because probationary actors
886
+ // still require strict verification. Never execute a stored verifier while
887
+ // drawing task reviews, status, queues, or projections.
888
+ const evaluation = evaluateAutoAccept(task, {
889
+ strictVerify: false,
890
+ minPasses: 0,
891
+ executeVerify: false,
892
+ });
887
893
  return evaluation && evaluation.reason === 'proof_unmerged_or_draft_pr_boundary'
888
894
  ? evaluation
889
895
  : null;
@@ -1583,9 +1589,74 @@ function enrichTaskProjection(projection) {
1583
1589
  },
1584
1590
  streams: buildTaskStreams(enrichedTasks, goalSource.goals),
1585
1591
  tasks: enrichedTasks,
1592
+ missions: projectionMissions(root),
1593
+ wishes: projectionWishes(root),
1586
1594
  };
1587
1595
  }
1588
1596
 
1597
+ // The desktop app renders projection.missions but the writer never filled it,
1598
+ // so live workers were invisible on every dashboard. Best-effort: a broken
1599
+ // mission or wish store must never take the task projection down with it.
1600
+ const PROJECTION_MISSION_LIMIT = 50;
1601
+ const PROJECTION_WISH_LIMIT = 30;
1602
+ const PROJECTION_CLIP = 240;
1603
+
1604
+ function clipForProjection(value) {
1605
+ const text = String(value || '');
1606
+ return text.length > PROJECTION_CLIP ? `${text.slice(0, PROJECTION_CLIP - 3)}...` : text;
1607
+ }
1608
+
1609
+ function projectionMissions(root) {
1610
+ try {
1611
+ const { listMissions } = require('./mission.js');
1612
+ const recentCutoff = Date.now() - 48 * 60 * 60 * 1000;
1613
+ return listMissions(root)
1614
+ .filter(mission => {
1615
+ const status = String(mission.status || '');
1616
+ if (!['complete', 'stopped'].includes(status)) return true;
1617
+ const updated = Date.parse(mission.updated_at || mission.created_at || '') || 0;
1618
+ return updated >= recentCutoff;
1619
+ })
1620
+ .slice(0, PROJECTION_MISSION_LIMIT)
1621
+ .map(mission => ({
1622
+ id: mission.id,
1623
+ objective: clipForProjection(String(mission.objective || '')),
1624
+ status: mission.status || null,
1625
+ owner: mission.owner || null,
1626
+ runner: mission.runner || null,
1627
+ cadence: mission.cadence || null,
1628
+ lane: mission.lane || null,
1629
+ next_action: clipForProjection(String(mission.next_action || '')),
1630
+ last_tick_at: mission.last_tick_at || null,
1631
+ last_tick_status: mission.last_tick_status || null,
1632
+ receipt_path: mission.receipt_path || null,
1633
+ wish_id: mission.wish_id || null,
1634
+ created_at: mission.created_at || null,
1635
+ updated_at: mission.updated_at || null,
1636
+ }));
1637
+ } catch {
1638
+ return [];
1639
+ }
1640
+ }
1641
+
1642
+ function projectionWishes(root) {
1643
+ try {
1644
+ const { readWishes } = require('../lib/wish-store');
1645
+ return readWishes(root)
1646
+ .filter(wish => String(wish.status || '') !== 'closed')
1647
+ .slice(-PROJECTION_WISH_LIMIT)
1648
+ .map(wish => ({
1649
+ id: wish.id,
1650
+ n: wish.n ?? null,
1651
+ text: clipForProjection(String(wish.text || '')),
1652
+ status: wish.status || null,
1653
+ created_at: wish.first_ts || wish.ts || null,
1654
+ }));
1655
+ } catch {
1656
+ return [];
1657
+ }
1658
+ }
1659
+
1589
1660
  function taskTypeForCloud(task) {
1590
1661
  const tag = String(task.tag || '').toLowerCase();
1591
1662
  if (['inbound', 'outbound', 'creative', 'improvement'].includes(tag)) return tag;
@@ -5442,19 +5513,17 @@ function taskReviewLandingLines(item) {
5442
5513
  function cmdReviews(args) {
5443
5514
  const taskDb = getTaskDb();
5444
5515
  const db = taskDb.open();
5445
- let { projection, outPath } = writeDefaultProjection(taskDb, db);
5446
- const workspaceRoot = projection.workspace_root || process.cwd();
5447
- const previousAutoAcceptState = readReviewAutoAcceptState(workspaceRoot);
5448
- const autoAcceptRun = autoAcceptCertifiedSmallReviews(taskDb, db, projection);
5449
- if (autoAcceptRun.changed) {
5450
- ({ projection, outPath } = writeDefaultProjection(taskDb, db));
5451
- }
5452
- const autoAcceptRollup = reviewAutoAcceptRollup(taskDb, db, workspaceRoot, previousAutoAcceptState, autoAcceptRun);
5453
- writeReviewAutoAcceptState(workspaceRoot, {
5454
- ...previousAutoAcceptState,
5455
- last_look_at: new Date().toISOString(),
5456
- last_count: autoAcceptRollup.count,
5457
- });
5516
+ const { projection, outPath } = writeDefaultProjection(taskDb, db);
5517
+ // Reviews is a view, not an execution lane. Certification and landing are
5518
+ // persisted by certify-verified, explicit receipt/ready commands, sweep,
5519
+ // and autoland; this command only reports that stored state.
5520
+ const autoAcceptView = {
5521
+ enabled: false,
5522
+ read_only: true,
5523
+ accepted_now: 0,
5524
+ accepted_since_last_look: 0,
5525
+ results: [],
5526
+ };
5458
5527
  const groupByRaw = flag(args, '--group-by');
5459
5528
  if (groupByRaw) {
5460
5529
  const key = reviewGroupKey(groupByRaw);
@@ -5464,20 +5533,12 @@ function cmdReviews(args) {
5464
5533
  ok: true,
5465
5534
  action: 'review_groups',
5466
5535
  projection_path: outPath,
5467
- autoaccept: {
5468
- enabled: autoAcceptRun.enabled,
5469
- accepted_now: autoAcceptRun.accepted,
5470
- accepted_since_last_look: autoAcceptRollup.count,
5471
- results: autoAcceptRun.results,
5472
- },
5536
+ autoaccept: autoAcceptView,
5473
5537
  groups,
5474
5538
  });
5475
5539
  return;
5476
5540
  }
5477
5541
  console.log(gateForHuman(`${numberWord(groups.total_certified)} finished things are waiting, grouped by ${key}.`).text);
5478
- if (autoAcceptRollup.count > 0) {
5479
- console.log(gateForHuman(`${numberWord(autoAcceptRollup.count)} landed on their own since you last looked.`).text);
5480
- }
5481
5542
  const visibleGroups = groups.groups.slice(0, reviewGroupTextLimit(args, groups.groups.length));
5482
5543
  visibleGroups.forEach((g, index) => {
5483
5544
  console.log('');
@@ -5498,12 +5559,7 @@ function cmdReviews(args) {
5498
5559
  ok: true,
5499
5560
  action: 'review_queue',
5500
5561
  projection_path: outPath,
5501
- autoaccept: {
5502
- enabled: autoAcceptRun.enabled,
5503
- accepted_now: autoAcceptRun.accepted,
5504
- accepted_since_last_look: autoAcceptRollup.count,
5505
- results: autoAcceptRun.results,
5506
- },
5562
+ autoaccept: autoAcceptView,
5507
5563
  queue,
5508
5564
  });
5509
5565
  return;
@@ -5512,9 +5568,6 @@ function cmdReviews(args) {
5512
5568
  const blockedItems = queue.items.filter(item => item.queue_role === 'blocked');
5513
5569
  if (!approvalItems.length && !blockedItems.length) {
5514
5570
  console.log('nothing is waiting on you. everything that finished has already landed.');
5515
- if (autoAcceptRollup.count > 0) {
5516
- console.log(gateForHuman(`${numberWord(autoAcceptRollup.count)} landed on their own since you last looked.`).text);
5517
- }
5518
5571
  return;
5519
5572
  }
5520
5573
  if (queue.counts.certified > 0) {
@@ -5528,12 +5581,13 @@ function cmdReviews(args) {
5528
5581
  ? 'one more is almost ready; a second check is still running.'
5529
5582
  : `${numberWord(queue.counts.blocking)} more are almost ready; second checks are still running.`).text);
5530
5583
  }
5531
- if (autoAcceptRollup.count > 0) {
5532
- console.log(gateForHuman(`${numberWord(autoAcceptRollup.count)} landed on their own since you last looked.`).text);
5533
- }
5534
5584
  approvalItems.forEach((item, index) => {
5535
5585
  if (index > 0) console.log('');
5536
- console.log(`${index + 1}. ${gateForHuman(item.title, { title: item.title }).text}`);
5586
+ const ref = item.display_id || taskRef(item.id);
5587
+ const badge = item.evidence?.any_forced
5588
+ ? ' [evidence:forced]'
5589
+ : item.evidence?.all_passing ? ' [evidence:passing]' : '';
5590
+ console.log(`${index + 1}. ${gateForHuman(item.title, { title: item.title }).text} (${ref})${badge}`);
5537
5591
  if (item.landing) {
5538
5592
  taskReviewLandingLines(item).forEach(line => console.log(line));
5539
5593
  if (verbose && item.result?.saved) console.log(` saved: ${item.result.saved}`);
@@ -9436,6 +9490,28 @@ async function cmdAccept(args) {
9436
9490
  if (missionXpIssue) {
9437
9491
  failTask('atris task accept', MISSION_XP_END_TO_END_REASON, missionXpIssue);
9438
9492
  }
9493
+ // The proof must be able to fail. Run the stored verify command and refuse the
9494
+ // accept if it does not parse, does not run, or does not pass. Prose describing a
9495
+ // check is not a check.
9496
+ const acceptVerify = evaluateAcceptVerify(beforeTask, taskDb.workspaceRoot());
9497
+ const verifyOverride = hasFlag(args, '--accept-unverified');
9498
+ const overrideReason = String(flag(args, '--reason') || '').trim();
9499
+ if (!acceptVerify.ok && !verifyOverride) {
9500
+ failTask(
9501
+ 'atris task accept',
9502
+ acceptVerify.reason,
9503
+ `${acceptVerify.detail}. Stored verify: ${acceptVerify.command || '(none)'}. `
9504
+ + 'Fix the verify command and re-run, or accept deliberately with '
9505
+ + '--accept-unverified --reason "why this cannot be machine-checked".',
9506
+ );
9507
+ }
9508
+ if (!acceptVerify.ok && verifyOverride && !overrideReason) {
9509
+ failTask(
9510
+ 'atris task accept',
9511
+ 'unverified_accept_needs_reason',
9512
+ '--accept-unverified records an unfalsifiable accept in the ledger, so it requires --reason "<why>".',
9513
+ );
9514
+ }
9439
9515
  const readyReview = beforeTask?.review || {};
9440
9516
  const clearLesson = hasEmptyFlagValue(args, '--lesson');
9441
9517
  const clearNextTask = hasEmptyFlagValue(args, '--next');
@@ -9923,11 +9999,19 @@ function cmdAutoAcceptCertified(args) {
9923
9999
  }
9924
10000
  const landingVerify = reverifyBeforeLanding(taskDb, db, task, { verifyCache });
9925
10001
  if (!landingVerify.ok) {
10002
+ // A refused landing whose revise also failed is the worst state in the
10003
+ // loop: the work does not land AND nobody is told to fix it, so the row
10004
+ // sits in review forever being re-refused every hour. Mark it so the
10005
+ // heartbeat can raise it instead of counting it as routine.
9926
10006
  results.push({
9927
10007
  ...evaluation,
9928
10008
  eligible: false,
9929
10009
  action: landingVerify.revised ? 'revised' : 'revise_failed',
9930
10010
  reason: landingVerify.result.reason || landingVerify.revise_reason || 'verify_failed',
10011
+ ...(landingVerify.result.unrunnable_cause
10012
+ ? { unrunnable_cause: landingVerify.result.unrunnable_cause }
10013
+ : {}),
10014
+ alarm: landingVerify.revised !== true || landingVerify.result.reason === 'verify_unrunnable',
9931
10015
  verify: landingVerify.verify,
9932
10016
  exit_code: landingVerify.result.status,
9933
10017
  revision_note: landingVerify.note,
@@ -12261,4 +12345,6 @@ module.exports = {
12261
12345
  delegateTask,
12262
12346
  AGENT_ENV_MARKERS,
12263
12347
  autoRenderTodoFromDb,
12348
+ projectionMissions,
12349
+ projectionWishes,
12264
12350
  };
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * atris teach — turn one bad turn into a permanent guard.
5
+ *
6
+ * atris teach list cases and which ones are guards
7
+ * atris teach add --id <id> --prompt "…" --require "<fragment>" [--complaint "…"]
8
+ * atris teach run [<id>] run one case (or all) and advance state
9
+ * atris teach guards rerun every promoted guard (regression suite)
10
+ *
11
+ * Thin shim over `python -m rl.teach` in the backend venv, which owns the
12
+ * red gate: a case must be observed FAILING before it can become a guard.
13
+ * Nonzero exit means a guard regressed.
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { spawnSync } = require('child_process');
19
+
20
+ const BACKEND_ROOT = '/Users/keshavrao/arena/atrisos-backend';
21
+
22
+ function requireVenvPython() {
23
+ const venvPython = path.join(BACKEND_ROOT, 'venv/bin/python');
24
+ if (!fs.existsSync(venvPython)) {
25
+ console.error(`✗ Backend venv not found: ${venvPython}`);
26
+ process.exit(1);
27
+ }
28
+ return venvPython;
29
+ }
30
+
31
+ function usage() {
32
+ console.log('atris teach — a bad turn becomes a failing benchmark, then a guard');
33
+ console.log('');
34
+ console.log(' atris teach list cases (red = not yet fixed, guard = protected)');
35
+ console.log(' atris teach add … record a misbehavior as a red case');
36
+ console.log(' atris teach run [<id>] run a case; a red case is SUPPOSED to fail');
37
+ console.log(' atris teach guards rerun every guard; nonzero exit = regression');
38
+ console.log(' atris teach drafts corrections captured from live turns');
39
+ console.log(' atris teach fix <id> brief a fix for a reproduced case (--dispatch to run it)');
40
+ console.log(' atris teach scaffold … turn a captured correction into a red case');
41
+ console.log(' atris teach mine which recorded tick failures could become cases');
42
+ console.log('');
43
+ console.log(' add flags: --id <kebab> --prompt "…" --require "<fragment>" (repeatable)');
44
+ console.log(' --complaint "…" --file path=@localfile --forbid-changed-files');
45
+ }
46
+
47
+ /**
48
+ * Map the operator-facing verbs onto `python -m rl.teach` arguments.
49
+ * Returns null for help.
50
+ */
51
+ function buildArgs(subcommand, args) {
52
+ if (!subcommand || subcommand === 'list') return ['list'];
53
+ if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') return null;
54
+ if (subcommand === 'add') return ['add', ...args];
55
+ if (subcommand === 'guards') return ['run', '--guards', ...args];
56
+ if (subcommand === 'mine') return ['mine', ...args];
57
+ if (subcommand === 'drafts') return ['drafts', ...args];
58
+ if (subcommand === 'fix') {
59
+ // `atris teach fix <id>` -> `fix --case <id>`
60
+ if (args.length && !args[0].startsWith('-')) return ['fix', '--case', args[0], ...args.slice(1)];
61
+ return ['fix', ...args];
62
+ }
63
+ if (subcommand === 'scaffold') return ['scaffold', ...args];
64
+ if (subcommand === 'run') {
65
+ // `atris teach run <id>` -> `run --case <id>`; bare `run` runs every case.
66
+ if (args.length && !args[0].startsWith('-')) return ['run', '--case', args[0], ...args.slice(1)];
67
+ return ['run', ...args];
68
+ }
69
+ // `atris teach <id>` is shorthand for running that one case.
70
+ if (!subcommand.startsWith('-')) return ['run', '--case', subcommand, ...args];
71
+ return null;
72
+ }
73
+
74
+ module.exports = function teach(subcommand, ...args) {
75
+ const moduleArgs = buildArgs(subcommand, args);
76
+ if (moduleArgs === null) {
77
+ usage();
78
+ return;
79
+ }
80
+ const result = spawnSync(requireVenvPython(), ['-m', 'rl.teach', ...moduleArgs], {
81
+ cwd: path.join(BACKEND_ROOT, 'backend'),
82
+ stdio: 'inherit',
83
+ });
84
+ process.exit(result.status === null ? 1 : result.status);
85
+ };
86
+
@@ -613,15 +613,5 @@ async function unknownsCommand(args = []) {
613
613
  module.exports = {
614
614
  unknownsCommand,
615
615
  showHelp,
616
- ensureUnknownsSchema,
617
- gatherTerritoryContext,
618
- buildUnknownsPrompt,
619
- analyzeWithModel,
620
- normalizeUnknowns,
621
- normalizeQuestions,
622
616
  fallbackPayload,
623
- insertUnknowns,
624
- listUnknownRows,
625
- renderUnknownsMarkdown,
626
- resolveUnknown,
627
617
  };
@@ -40,5 +40,4 @@ function updateSelf(options = {}) {
40
40
 
41
41
  module.exports = {
42
42
  updateSelf,
43
- DEFAULT_PACKAGE_ROOT,
44
43
  };
@@ -389,9 +389,4 @@ async function visualizeAtris(args = process.argv.slice(3)) {
389
389
 
390
390
  module.exports = {
391
391
  visualizeAtris,
392
- parseVisualizeArgs,
393
- buildImagePrompt,
394
- classifyArtifact,
395
- resolveOutputPath,
396
- generateVisual,
397
392
  };
package/commands/watch.js CHANGED
@@ -293,11 +293,5 @@ function watchAtris() {
293
293
 
294
294
  module.exports = {
295
295
  watchAtris,
296
- watchCommand,
297
- showWatchHelp,
298
296
  slugify,
299
- buildWatchObjective,
300
- activeWatchMissions,
301
- resolveWatchMission,
302
- watchStatePath,
303
297
  };
package/commands/wiki.js CHANGED
@@ -14,8 +14,11 @@ const {
14
14
  buildIngestPrompt,
15
15
  buildQueryPrompt,
16
16
  buildLintPrompt,
17
+ buildConsolidatePrompt,
17
18
  writeWikiStatus,
18
19
  appendWikiLog,
20
+ findWikiMetabolismFindings,
21
+ recordWikiConsolidation,
19
22
  validateAgentReadableWikiPages,
20
23
  } = require('../lib/wiki');
21
24
 
@@ -171,7 +174,7 @@ function hasHelpFlag(args) {
171
174
  }
172
175
 
173
176
  function printWikiHelp(scope = null) {
174
- const normalized = scope === 'ingest' || scope === 'query' || scope === 'lint' || scope === 'search' || scope === 'log' || scope === 'loop' || scope === 'verify'
177
+ const normalized = scope === 'ingest' || scope === 'query' || scope === 'lint' || scope === 'consolidate' || scope === 'search' || scope === 'log' || scope === 'loop' || scope === 'verify'
175
178
  ? scope
176
179
  : null;
177
180
 
@@ -191,12 +194,17 @@ function printWikiHelp(scope = null) {
191
194
  console.log('Usage: atris wiki lint [--private|--cloud] [business]');
192
195
  console.log('');
193
196
  console.log('Build a local or cloud wiki lint prompt.');
197
+ } else if (normalized === 'consolidate') {
198
+ console.log('Usage: atris wiki consolidate [--private]');
199
+ console.log('');
200
+ console.log('Build a local wiki pruning prompt and reset the growth marker.');
194
201
  } else {
195
- console.log('Usage: atris wiki <ingest|query|lint|search|log|loop|verify|entities|related> [business] [args]');
202
+ console.log('Usage: atris wiki <ingest|query|lint|consolidate|search|log|loop|verify|entities|related> [business] [args]');
196
203
  console.log('');
197
204
  console.log(' ingest <path> Local-first ingest into atris/wiki/');
198
205
  console.log(' query "question" Local-first query against atris/wiki/');
199
206
  console.log(' lint Local-first lint for atris/wiki/');
207
+ console.log(' consolidate Build a local pruning prompt and reset wiki growth');
200
208
  console.log(' search [business] <term> Search local atris/wiki/index.md');
201
209
  console.log(' log [business] [N] Show recent atris/wiki/log.md entries');
202
210
  console.log(' loop Run local wiki upkeep analysis and refresh STATUS/log');
@@ -366,7 +374,11 @@ async function wikiLint(mode, slug) {
366
374
  console.error(`No local wiki found at ${getWikiRoot(wikiMode)}. Run: atris wiki ingest${wikiMode === 'private' ? ' --private' : ''} <path>`);
367
375
  process.exit(1);
368
376
  }
369
- printLocalPrompt(mode === 'private' ? 'Private wiki lint' : 'Local wiki lint', buildLintPrompt(wikiMode), getWikiRoot(wikiMode), [`Wiki dir: ${wikiDir}`]);
377
+ const metabolismFindings = findWikiMetabolismFindings(process.cwd(), wikiMode);
378
+ printLocalPrompt(mode === 'private' ? 'Private wiki lint' : 'Local wiki lint', buildLintPrompt(wikiMode), getWikiRoot(wikiMode), [
379
+ `Wiki dir: ${wikiDir}`,
380
+ ...metabolismFindings.map((finding) => `${finding.code}: ${finding.message}`),
381
+ ]);
370
382
  return;
371
383
  }
372
384
 
@@ -376,6 +388,28 @@ async function wikiLint(mode, slug) {
376
388
  await runChat(business, buildLintPrompt(), creds.token);
377
389
  }
378
390
 
391
+ function wikiConsolidate(mode, slug) {
392
+ if (mode === 'cloud') {
393
+ console.error('Wiki consolidation is local-only. Pull the wiki before consolidating it.');
394
+ process.exit(1);
395
+ }
396
+
397
+ const wikiMode = mode === 'private' ? 'private' : 'public';
398
+ const wikiDir = findLocalWikiDir(process.cwd(), slug, wikiMode);
399
+ if (!wikiDir) {
400
+ console.error(`No local wiki found at ${getWikiRoot(wikiMode)}.`);
401
+ process.exit(1);
402
+ }
403
+
404
+ printLocalPrompt(
405
+ mode === 'private' ? 'private wiki consolidate' : 'local wiki consolidate',
406
+ buildConsolidatePrompt(wikiMode),
407
+ getWikiRoot(wikiMode),
408
+ [`wiki dir: ${wikiDir}`]
409
+ );
410
+ recordWikiConsolidation(process.cwd(), wikiMode);
411
+ }
412
+
379
413
  function wikiSearch(mode, slug, query) {
380
414
  if (!query) {
381
415
  console.error('Usage: atris wiki search [business] <term>');
@@ -513,6 +547,10 @@ async function wikiCommand(subcommand, ...args) {
513
547
  await wikiLint(mode, slug);
514
548
  break;
515
549
  }
550
+ case 'consolidate': {
551
+ wikiConsolidate(mode, null);
552
+ break;
553
+ }
516
554
  case 'search': {
517
555
  if (mode === 'private') {
518
556
  wikiSearch(mode, null, cleanArgs.join(' '));
@@ -572,12 +610,4 @@ async function wikiCommand(subcommand, ...args) {
572
610
 
573
611
  module.exports = {
574
612
  wikiCommand,
575
- wikiIngest,
576
- wikiQuery,
577
- wikiLint,
578
- wikiSearch,
579
- wikiLog,
580
- wikiVerify,
581
- wikiEntities,
582
- wikiRelated,
583
613
  };
package/commands/wish.js CHANGED
@@ -487,7 +487,6 @@ module.exports = {
487
487
  printRewards,
488
488
  readWishEvents,
489
489
  readWishes,
490
- runCloudWish,
491
490
  runAgainWish,
492
491
  sayWish,
493
492
  sharesMeaningfulWords,