atris 3.74.15 → 3.74.16

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.
@@ -981,9 +981,39 @@ function inferMemberRunVerifier(missionText, args = [], cwd = process.cwd()) {
981
981
  // chose that check; it is not a silent broad-suite default.
982
982
  const npmMatch = text.match(/\bnpm\s+(run\s+)?test(?![\w:-]|\.\w)/i);
983
983
  if (npmMatch && projectHasTestScript(cwd)) return npmMatch[1] ? 'npm run test' : 'npm test';
984
+ // A named test file in a project that runs node's own test runner: check
985
+ // just that file, since other files may fail on purpose ("legacy.js is out
986
+ // of scope"). Member lab: these jobs fell back to a whitespace check.
987
+ // Only sentences that ask for the work count; "x is out of scope" or "do not
988
+ // run the failing tests" must not pick a check.
989
+ const asks = text.split(/[;,\n]+|\.(?=\s|$)|\s(?:and|but)\s/i).filter((part) => part.trim()
990
+ && !/\b(out\s+of\s+scope|do\s+not|don't|never|without|skip|ignore|leave|except|known\s+bug|reference)\b/i.test(part)).join('. ');
991
+ const testScript = projectTestScript(cwd);
992
+ // The project runs node's test runner itself, not as part of another command.
993
+ if (/^\s*node\s+--test\b/.test(testScript) && !/&&|\|\||[;|]/.test(testScript)) {
994
+ const root = path.resolve(cwd);
995
+ const named = (asks.match(/[\w./-]+\.[cm]?js\b/g) || [])
996
+ .filter((file) => /(^|\/)(tests?|checks?|specs?|__tests__)\/|\.(test|spec)\.[cm]?js$/.test(file))
997
+ .filter((file) => !path.isAbsolute(file) && path.resolve(root, file).startsWith(`${root}${path.sep}`))
998
+ .find((file) => fs.existsSync(path.join(root, file)));
999
+ if (named) return `node --test ${named}`;
1000
+ }
1001
+ // "fix the failing tests" names the project's tests as the target.
1002
+ if (testScript && /\b(fail(ing|ed)?\s+(\w+\s+){0,3}tests?|tests?\s+(pass|green)|fix\s+the\s+(\w+\s+){0,2}tests?)\b/i.test(asks)) {
1003
+ return 'npm test';
1004
+ }
984
1005
  return '';
985
1006
  }
986
1007
 
1008
+ function projectTestScript(cwd) {
1009
+ try {
1010
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
1011
+ return String(pkg?.scripts?.test || '');
1012
+ } catch {
1013
+ return '';
1014
+ }
1015
+ }
1016
+
987
1017
  function projectHasTestScript(cwd) {
988
1018
  try {
989
1019
  const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
@@ -1069,6 +1099,16 @@ function startMemberRunMission(name, missionText, args = []) {
1069
1099
  // second engine only reran the same commands and cost about a minute a run
1070
1100
  // (member lab 2026-10-24), so it stays for runs whose check is not a test
1071
1101
  // runner (whitespace, syntax, or file-exists checks). --no-referee skips it; an explicit --referee is kept.
1102
+ // 'checked' when the run passed, 'unchecked' when the only thing missing is a
1103
+ // reviewer verdict (timed out or could not start), '' otherwise.
1104
+ function memberRunSaveDecision({ started, ok, verdict } = {}) {
1105
+ if (!started) return '';
1106
+ const v = verdict || {};
1107
+ if (v.passed === true) return ok ? 'checked' : '';
1108
+ const reviewerGone = v.referee?.mode === 'engine-unavailable' || v.mode === 'engine-unavailable';
1109
+ return reviewerGone && (v.status === undefined || v.status === 0) ? 'unchecked' : '';
1110
+ }
1111
+
1072
1112
  function memberRunHasRealCheck(verifier) {
1073
1113
  const command = String(verifier || '').trim();
1074
1114
  // A plain test runner only: chaining (|| true, ; , &&, pipes, subshells) or a
@@ -1468,13 +1508,22 @@ function memberRunWith(name, args, { quiet = false, closeTaskIds = [] } = {}) {
1468
1508
  }
1469
1509
  // Passed but never committed: save the loose work on the member's branch so
1470
1510
  // the branch holds it. Only in the member's own side checkout, never the main one.
1511
+ // A reviewer that timed out or could not start gave no verdict; the work is
1512
+ // unchecked, not rejected, so save it too (member lab: a correct answer was
1513
+ // lost when the reviewer hit its time limit on a busy machine). Landing still
1514
+ // needs a real pass.
1471
1515
  const worktreePath = finalMission.worktree?.path || mission.worktree?.path || '';
1472
- if (ok && started && worktreePath && finalMission.verifier_result?.passed === true) {
1516
+ const saveDecision = memberRunSaveDecision({ started, ok, verdict: finalMission.verifier_result });
1517
+ const reviewerUnavailable = saveDecision === 'unchecked';
1518
+ if (worktreePath && saveDecision) {
1473
1519
  result.saved_work = require('../lib/member-save-work').saveLeftoverMemberWork({
1474
1520
  worktreePath, member: name, objective: finalMission.objective || mission.objective,
1475
1521
  });
1522
+ if (reviewerUnavailable) result.saved_work.unchecked = true;
1476
1523
  if (result.saved_work.saved && !asJson && !quiet) {
1477
- console.log(`saved ${result.saved_work.files.length} file(s) ${name} left unsaved onto its branch`);
1524
+ console.log(reviewerUnavailable
1525
+ ? `saved ${result.saved_work.files.length} file(s) onto ${name}'s branch, not checked yet: the reviewer timed out or could not start`
1526
+ : `saved ${result.saved_work.files.length} file(s) ${name} left unsaved onto its branch`);
1478
1527
  }
1479
1528
  }
1480
1529
  // A finished ignited run whose check passed hands its branch to GitHub
@@ -12140,6 +12189,7 @@ module.exports = {
12140
12189
  wakeBootLines,
12141
12190
  buildMemberRunStartArgs,
12142
12191
  inferMemberRunVerifier,
12192
+ memberRunSaveDecision,
12143
12193
  buildMemberSubagentShell,
12144
12194
  pickMemberForIdea,
12145
12195
  appendMemberGoalLog,
@@ -9997,6 +9997,9 @@ function buildEngineVerifyPrompt(mission, tickIndex, doneLooksLike = '', { timeo
9997
9997
  `Split that line into each separate thing it promises and check every one. List each part as met or missing.`,
9998
9998
  `Work that does only some of the parts is not done. If any part is missing, end with 'VERDICT: FAIL; missing: <that part>'.`,
9999
9999
  ] : []),
10000
+ // Member lab: reviewers spent about half their time on the workspace boot
10001
+ // (atris atris.md, MAP, PERSONA, skills) before reading the change.
10002
+ `Skip any workspace boot or start-of-session routine the folder's instructions ask for: do not run \`atris atris.md\` and do not read MAP.md, PERSONA.md, FOR_AGENTS.md, or skill files. Start with \`git diff\` and the changed files.`,
10000
10003
  `Read the diff this tick produced. Do not edit files and do not start another work slice.`,
10001
10004
  `ACTUALLY RUN the changed surface on this computer using real commands and real exit codes.`,
10002
10005
  `Paste the commands and their real output. Do not accept a receipt claim or static inspection as execution proof.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.74.15",
3
+ "version": "3.74.16",
4
4
  "description": "you say what you want in plain words. atris builds it, checks it, and shows you proof.",
5
5
  "mcpName": "io.github.atrislabs/atris",
6
6
  "main": "bin/atris.js",