atris 3.31.0 → 3.33.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.
- package/README.md +46 -4
- package/atris/CLAUDE.md +8 -0
- package/atris.md +8 -0
- package/ax +458 -15
- package/bin/atris.js +200 -76
- package/commands/autoland.js +78 -12
- package/commands/autopilot-front.js +273 -0
- package/commands/engine.js +299 -0
- package/commands/init.js +21 -0
- package/commands/integrations.js +147 -0
- package/commands/member.js +85 -0
- package/commands/mission.js +500 -43
- package/commands/run-front.js +144 -0
- package/commands/run.js +9 -6
- package/commands/sign.js +90 -0
- package/commands/task.js +380 -20
- package/commands/truth.js +72 -11
- package/lib/autoland.js +133 -25
- package/lib/fleet.js +354 -0
- package/lib/inspect-fields.js +174 -0
- package/lib/operator-next.js +7 -0
- package/lib/pulse.js +4 -3
- package/lib/runner-command.js +54 -11
- package/lib/task-db.js +57 -2
- package/package.json +3 -2
- package/scripts/agent_worktree.py +72 -0
package/lib/task-db.js
CHANGED
|
@@ -469,6 +469,43 @@ function claimTask(db, { id, claimedBy }) {
|
|
|
469
469
|
return { claimed: false, reason: 'already_' + row.status, claimed_by: row.claimed_by };
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
function releaseTask(db, { id, actor }) {
|
|
473
|
+
if (!id) throw new Error('id required');
|
|
474
|
+
if (!actor) throw new Error('actor required');
|
|
475
|
+
const row = getTask(db, id);
|
|
476
|
+
if (!row) return { released: false, reason: 'not_found' };
|
|
477
|
+
if (row.status !== 'claimed') {
|
|
478
|
+
return { released: false, reason: `already_${row.status}`, claimed_by: row.claimed_by || null };
|
|
479
|
+
}
|
|
480
|
+
if (row.claimed_by !== actor) {
|
|
481
|
+
return { released: false, reason: 'held_by_other', claimed_by: row.claimed_by || null };
|
|
482
|
+
}
|
|
483
|
+
const now = Date.now();
|
|
484
|
+
const result = withBusyRetry(() => db.prepare(`
|
|
485
|
+
UPDATE tasks
|
|
486
|
+
SET status = 'open',
|
|
487
|
+
claimed_by = NULL,
|
|
488
|
+
claimed_at = NULL,
|
|
489
|
+
updated_at = ?
|
|
490
|
+
WHERE id = ?
|
|
491
|
+
AND status = 'claimed'
|
|
492
|
+
AND claimed_by = ?
|
|
493
|
+
`).run(now, id, actor));
|
|
494
|
+
if (result.changes !== 1) return { released: false, reason: 'stale_task_state', claimed_by: row.claimed_by || null };
|
|
495
|
+
const updated = getTask(db, id);
|
|
496
|
+
const event = appendTaskEvent(db, {
|
|
497
|
+
taskId: id,
|
|
498
|
+
workspaceRoot: updated.workspace_root,
|
|
499
|
+
actor,
|
|
500
|
+
eventType: 'claim_released',
|
|
501
|
+
payload: {
|
|
502
|
+
released_by: actor,
|
|
503
|
+
previous_claimed_by: row.claimed_by || null,
|
|
504
|
+
},
|
|
505
|
+
});
|
|
506
|
+
return { released: true, row: updated, event };
|
|
507
|
+
}
|
|
508
|
+
|
|
472
509
|
function doneTask(db, { id, status, actor, allowReview = false, action, proof } = {}) {
|
|
473
510
|
if (!id) throw new Error('id required');
|
|
474
511
|
const final = status || 'done';
|
|
@@ -1198,7 +1235,7 @@ function chatTask(db, { id, actor, content, goal, summary }) {
|
|
|
1198
1235
|
};
|
|
1199
1236
|
}
|
|
1200
1237
|
|
|
1201
|
-
function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, careerXpEligible = false, clearedFields = [] }) {
|
|
1238
|
+
function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, careerXpEligible = false, clearedFields = [], landing = {} }) {
|
|
1202
1239
|
if (!id) throw new Error('id required');
|
|
1203
1240
|
const row = getTask(db, id);
|
|
1204
1241
|
if (!row) return { reviewed: false, reason: 'not_found' };
|
|
@@ -1213,6 +1250,15 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1213
1250
|
const clearedReviewFields = Array.isArray(clearedFields)
|
|
1214
1251
|
? Array.from(new Set(clearedFields.filter(field => field === 'lesson' || field === 'next_task')))
|
|
1215
1252
|
: [];
|
|
1253
|
+
const landingInput = landing && typeof landing === 'object' ? landing : {};
|
|
1254
|
+
let landingUpdated = false;
|
|
1255
|
+
for (const key of ['happened', 'checked', 'tested', 'decision']) {
|
|
1256
|
+
const cleaned = cleanLandingText(landingInput[key]);
|
|
1257
|
+
if (cleaned) {
|
|
1258
|
+
metadata[`landing_${key}`] = cleaned;
|
|
1259
|
+
landingUpdated = true;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1216
1262
|
const reviewingPendingProof = row.status === 'review'
|
|
1217
1263
|
&& metadata.approval_status === 'pending'
|
|
1218
1264
|
&& numericReward <= 0
|
|
@@ -1250,7 +1296,7 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1250
1296
|
metadata.accepted_at = new Date().toISOString();
|
|
1251
1297
|
metadata.accepted_by = reviewer;
|
|
1252
1298
|
}
|
|
1253
|
-
if (reviewingPendingProof || updatingPendingReviewProof || (numericReward > 0 && row.status === 'done')) {
|
|
1299
|
+
if (reviewingPendingProof || updatingPendingReviewProof || (numericReward > 0 && row.status === 'done') || landingUpdated) {
|
|
1254
1300
|
withBusyRetry(() => db.prepare(`
|
|
1255
1301
|
UPDATE tasks
|
|
1256
1302
|
SET metadata = ?,
|
|
@@ -1271,6 +1317,14 @@ function reviewTask(db, { id, actor, reward, lesson, nextTask, proof, verify, ca
|
|
|
1271
1317
|
payload.agent_certified = metadata.agent_certified === true;
|
|
1272
1318
|
payload.agent_certification_policy = metadata.agent_certification_policy || null;
|
|
1273
1319
|
}
|
|
1320
|
+
if (landingUpdated) {
|
|
1321
|
+
payload.landing = {
|
|
1322
|
+
happened: metadata.landing_happened || null,
|
|
1323
|
+
checked: metadata.landing_checked || null,
|
|
1324
|
+
tested: metadata.landing_tested || null,
|
|
1325
|
+
decision: metadata.landing_decision || null,
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1274
1328
|
if (clearedReviewFields.length) payload.cleared_review_fields = clearedReviewFields;
|
|
1275
1329
|
const event = appendTaskEvent(db, {
|
|
1276
1330
|
taskId: id,
|
|
@@ -1704,6 +1758,7 @@ module.exports = {
|
|
|
1704
1758
|
getTask,
|
|
1705
1759
|
listTasks,
|
|
1706
1760
|
claimTask,
|
|
1761
|
+
releaseTask,
|
|
1707
1762
|
backlogTask,
|
|
1708
1763
|
clearPlanTasks,
|
|
1709
1764
|
doneTask,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "atris",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.33.3",
|
|
4
4
|
"main": "bin/atris.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"atris": "bin/atris.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"cli/*.py",
|
|
13
13
|
"commands/",
|
|
14
14
|
"decks/",
|
|
15
|
+
"scripts/agent_worktree.py",
|
|
15
16
|
"utils/",
|
|
16
17
|
"lib/",
|
|
17
18
|
"templates/",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"test": "node --test",
|
|
56
57
|
"lint:decks": "node scripts/lint-all-decks.js",
|
|
57
58
|
"publish:release": "node scripts/publish-atris-release.js",
|
|
58
|
-
"prepare": "cp scripts/pre-commit .git/hooks/pre-commit 2>/dev/null && chmod +x .git/hooks/pre-commit || true"
|
|
59
|
+
"prepare": "cp scripts/pre-commit .git/hooks/pre-commit 2>/dev/null && cp scripts/commit-msg .git/hooks/commit-msg 2>/dev/null && cp scripts/prepare-commit-msg .git/hooks/prepare-commit-msg 2>/dev/null && chmod +x .git/hooks/pre-commit .git/hooks/commit-msg .git/hooks/prepare-commit-msg || true"
|
|
59
60
|
},
|
|
60
61
|
"keywords": [
|
|
61
62
|
"atrisdev",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Compatibility wrapper for older agent worktree instructions.
|
|
3
|
+
|
|
4
|
+
Use the canonical Atris CLI:
|
|
5
|
+
atris worktree start --agent <agent> --task "<task>"
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
17
|
+
parser = argparse.ArgumentParser(
|
|
18
|
+
prog="scripts/agent_worktree.py",
|
|
19
|
+
description="Compatibility wrapper around `atris worktree start`.",
|
|
20
|
+
)
|
|
21
|
+
subcommands = parser.add_subparsers(dest="command", required=True)
|
|
22
|
+
|
|
23
|
+
create = subcommands.add_parser("create", help="Create an Atris agent worktree.")
|
|
24
|
+
owner = create.add_mutually_exclusive_group(required=True)
|
|
25
|
+
owner.add_argument("--agent")
|
|
26
|
+
owner.add_argument("--member")
|
|
27
|
+
create.add_argument("--task", required=True)
|
|
28
|
+
create.add_argument("--base")
|
|
29
|
+
create.add_argument("--path")
|
|
30
|
+
create.add_argument("--branch")
|
|
31
|
+
create.add_argument("--claim", action="store_true")
|
|
32
|
+
return parser
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main(argv: list[str]) -> int:
|
|
36
|
+
args = build_parser().parse_args(argv)
|
|
37
|
+
repo_root = Path(__file__).resolve().parents[1]
|
|
38
|
+
atris_bin = repo_root / "bin" / "atris.js"
|
|
39
|
+
|
|
40
|
+
# Run the Node CLI directly so this wrapper works before a global `atris`
|
|
41
|
+
# binary is on PATH.
|
|
42
|
+
command = ["node", str(atris_bin), "worktree", "start"]
|
|
43
|
+
display = ["atris", "worktree", "start"]
|
|
44
|
+
if args.member:
|
|
45
|
+
command += ["--member", args.member]
|
|
46
|
+
display += ["--member", args.member]
|
|
47
|
+
else:
|
|
48
|
+
command += ["--agent", args.agent]
|
|
49
|
+
display += ["--agent", args.agent]
|
|
50
|
+
command += ["--task", args.task]
|
|
51
|
+
display += ["--task", args.task]
|
|
52
|
+
if args.base:
|
|
53
|
+
command += ["--base", args.base]
|
|
54
|
+
display += ["--base", args.base]
|
|
55
|
+
if args.path:
|
|
56
|
+
command += ["--path", args.path]
|
|
57
|
+
display += ["--path", args.path]
|
|
58
|
+
if args.branch:
|
|
59
|
+
command += ["--branch", args.branch]
|
|
60
|
+
display += ["--branch", args.branch]
|
|
61
|
+
if args.claim:
|
|
62
|
+
command.append("--claim")
|
|
63
|
+
display.append("--claim")
|
|
64
|
+
|
|
65
|
+
print("compat: scripts/agent_worktree.py maps to:")
|
|
66
|
+
print(f" {' '.join(display)}")
|
|
67
|
+
result = subprocess.run(command)
|
|
68
|
+
return int(result.returncode or 0)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if __name__ == "__main__":
|
|
72
|
+
raise SystemExit(main(sys.argv[1:]))
|