atris 3.57.1 → 3.57.3

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.
@@ -443,8 +443,16 @@ async function gmailTriage(options = {}) {
443
443
  const accountId = resolveGmailAccountId(options.accountId);
444
444
  const limit = Number.isInteger(options.limit) && options.limit > 0 ? options.limit : 25;
445
445
  const messages = await gmailInbox({ accountId, limit, quiet: true });
446
+ // The hourly pass rereads the newest window, so without this filter a message
447
+ // gets one row per hour it lingers and counts measure dwell time, not preference.
448
+ const seen = new Set(
449
+ readGmailVerdicts({ root: options.root, filePath: options.filePath, account: accountId, limit: null })
450
+ .map((row) => row.message_id),
451
+ );
452
+ const fresh = messages.filter((message) => !seen.has(String(message.id || message.message_id || '')));
453
+ const skipped = messages.length - fresh.length;
446
454
  const ts = new Date().toISOString();
447
- const rows = messages.map((message) => {
455
+ const rows = fresh.map((message) => {
448
456
  const { verdict, reason } = gmailTriageVerdict(message, { details: true });
449
457
  return {
450
458
  ts,
@@ -460,7 +468,8 @@ async function gmailTriage(options = {}) {
460
468
 
461
469
  const keepCount = rows.filter((row) => row.verdict === 'keep').length;
462
470
  const archiveCount = rows.length - keepCount;
463
- console.log(`gmail triage recorded ${keepCount} keep and ${archiveCount} archive verdict${rows.length === 1 ? '' : 's'}.`);
471
+ const skippedNote = skipped > 0 ? ` (${skipped} already judged)` : '';
472
+ console.log(`gmail triage recorded ${keepCount} keep and ${archiveCount} archive verdict${rows.length === 1 ? '' : 's'}${skippedNote}.`);
464
473
  return rows;
465
474
  }
466
475
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.57.1",
3
+ "version": "3.57.3",
4
4
  "description": "you say what you want in plain words. atris builds it, checks it, and shows you proof.",
5
5
  "main": "bin/atris.js",
6
6
  "bin": {
@@ -77,8 +77,26 @@ const agent = String(readFlag(args, '--agent', '')).trim().toLowerCase();
77
77
  const model = String(readFlag(args, '--model', '')).trim();
78
78
 
79
79
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
80
- const atrisBin = process.env.ATRIS_BIN || path.join(scriptDir, '..', 'bin', 'atris.js');
81
- if (!fs.existsSync(atrisBin)) {
80
+ // Resolution order: explicit env, repo checkout beside this script, then the
81
+ // installed CLI on PATH (cloud workspaces carry this script without the repo).
82
+ function resolveAtrisBin() {
83
+ const candidates = [
84
+ process.env.ATRIS_BIN,
85
+ path.join(scriptDir, '..', 'bin', 'atris.js'),
86
+ ].filter(Boolean);
87
+ for (const candidate of candidates) {
88
+ if (fs.existsSync(candidate)) return candidate;
89
+ }
90
+ const pathDirs = String(process.env.PATH || '').split(path.delimiter);
91
+ for (const dir of pathDirs) {
92
+ if (!dir) continue;
93
+ const candidate = path.join(dir, 'atris');
94
+ if (fs.existsSync(candidate)) return candidate;
95
+ }
96
+ return null;
97
+ }
98
+ const atrisBin = resolveAtrisBin();
99
+ if (!atrisBin) {
82
100
  finish({ ok: false, reason: 'atris_bin_not_found', member, executed: false });
83
101
  }
84
102