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.
- package/README.md +2 -0
- package/atris/PERSONA.md +3 -7
- package/atris.md +10 -2
- package/ax +158 -33
- package/bin/atris.js +49 -2
- package/commands/activate.js +16 -3
- package/commands/agent-spawn.js +0 -7
- package/commands/autoland.js +92 -14
- package/commands/autopilot-front.js +0 -4
- package/commands/autopilot.js +0 -12
- package/commands/brain.js +0 -7
- package/commands/brief.js +0 -2
- package/commands/business-sync.js +0 -1
- package/commands/business.js +107 -12
- package/commands/clean.js +31 -2
- package/commands/close.js +46 -11
- package/commands/cloud.js +0 -1
- package/commands/codex-goal.js +0 -2
- package/commands/computer.js +6 -5
- package/commands/console.js +46 -9
- package/commands/deck.js +29 -8
- package/commands/dream.js +0 -7
- package/commands/drill.js +0 -1
- package/commands/engine.js +10 -18
- package/commands/experiments.js +0 -4
- package/commands/fleet-report.js +12 -4
- package/commands/game.js +261 -0
- package/commands/gm.js +10 -2
- package/commands/goal.js +0 -6
- package/commands/harvest.js +0 -1
- package/commands/improve.js +29 -8
- package/commands/init.js +18 -34
- package/commands/integrations.js +0 -7
- package/commands/land.js +71 -8
- package/commands/launchpad.js +0 -2
- package/commands/lesson.js +17 -7
- package/commands/loop-front.js +0 -2
- package/commands/loops.js +6 -5
- package/commands/meet.js +0 -2
- package/commands/member.js +68 -3
- package/commands/mission.js +359 -102
- package/commands/next.js +0 -1
- package/commands/now.js +0 -12
- package/commands/one-lap.js +8 -8
- package/commands/orb.js +0 -4
- package/commands/pack-craft.js +0 -1
- package/commands/pack.js +670 -77
- package/commands/play.js +0 -2
- package/commands/probe.js +10 -4
- package/commands/pulse.js +73 -48
- package/commands/push.js +0 -4
- package/commands/radar.js +14 -11
- package/commands/recover.js +340 -0
- package/commands/report.js +0 -1
- package/commands/router.js +319 -0
- package/commands/run-front.js +0 -2
- package/commands/search.js +0 -3
- package/commands/skill.js +7 -2
- package/commands/slop.js +225 -7
- package/commands/status.js +6 -0
- package/commands/stream.js +0 -2
- package/commands/study.js +0 -3
- package/commands/sync-checkout.js +51 -0
- package/commands/sync.js +11 -40
- package/commands/task.js +125 -39
- package/commands/teach.js +86 -0
- package/commands/unknowns.js +0 -10
- package/commands/update.js +0 -1
- package/commands/visualize.js +0 -5
- package/commands/watch.js +0 -6
- package/commands/wiki.js +41 -11
- package/commands/wish.js +0 -1
- package/commands/worktree.js +87 -14
- package/commands/xp.js +1 -6
- package/commands/youtube.js +0 -2
- package/lib/accept-verify-gate.js +122 -0
- package/lib/activity-stream.js +0 -2
- package/lib/auto-accept-certified.js +145 -2
- package/lib/autoland.js +0 -3
- package/lib/ax-auto-lane.js +94 -10
- package/lib/bench/context.js +0 -2
- package/lib/bench/report.js +0 -1
- package/lib/bench/runner.js +0 -11
- package/lib/brief-ledger.js +0 -6
- package/lib/business-simulate.js +382 -0
- package/lib/chat-log-scan.js +0 -5
- package/lib/checkout-sync.js +52 -0
- package/lib/claude-boot-block.js +48 -0
- package/lib/cloud-mission.js +0 -6
- package/lib/codex-flight.js +0 -1
- package/lib/conductor-artifacts.js +25 -0
- package/lib/context-gatherer.js +0 -1
- package/lib/deck-compose.js +0 -1
- package/lib/deck-history.js +0 -1
- package/lib/deck-layout.js +0 -5
- package/lib/deck-review.js +0 -7
- package/lib/deck-schema.js +0 -1
- package/lib/default-verifier.js +0 -2
- package/lib/engine-registry.js +16 -8
- package/lib/experiments/daily.js +0 -6
- package/lib/fleet.js +210 -27
- package/lib/functional-owner.js +0 -3
- package/lib/inspect-fields.js +0 -1
- package/lib/known-commands.js +2 -2
- package/lib/learnings.js +0 -2
- package/lib/loop-doctor.js +11 -17
- package/lib/manifest.js +0 -2
- package/lib/member-alive.js +0 -1
- package/lib/member-switches.js +0 -5
- package/lib/mission-artifact.js +0 -1
- package/lib/mission-protected-lane.js +293 -0
- package/lib/mission-room.js +0 -2
- package/lib/mission-runtime-loop.js +0 -1
- package/lib/next-moves.js +0 -18
- package/lib/official-cli-integration.js +0 -4
- package/lib/orb-context.js +6 -3
- package/lib/orb-scorecard.js +0 -1
- package/lib/outbound-send-gate.js +0 -6
- package/lib/permission-grants.js +0 -6
- package/lib/policy-lessons.js +0 -2
- package/lib/pulse.js +68 -15
- package/lib/review-integrity.js +0 -2
- package/lib/router-brain.js +0 -2
- package/lib/runner-command.js +0 -4
- package/lib/runtime-bootstrap.js +0 -1
- package/lib/scorecard.js +0 -1
- package/lib/self-drive.js +1 -1
- package/lib/state-detection.js +0 -6
- package/lib/task-db.js +0 -4
- package/lib/team-presence.js +0 -1
- package/lib/voice-gate.js +63 -2
- package/lib/wiki.js +152 -9
- package/lib/wish-audit.js +20 -6
- package/lib/wish-delegate.js +26 -20
- package/lib/wish-stats.js +0 -5
- package/lib/wish-store.js +0 -1
- package/lib/workspace-safety.js +0 -2
- package/lib/zip.js +0 -1
- 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
|
-
//
|
|
884
|
-
//
|
|
885
|
-
//
|
|
886
|
-
|
|
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
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
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
|
-
|
|
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
|
+
|
package/commands/unknowns.js
CHANGED
|
@@ -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
|
};
|
package/commands/update.js
CHANGED
package/commands/visualize.js
CHANGED
package/commands/watch.js
CHANGED
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
|
-
|
|
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
|
};
|