atris 3.15.56 → 3.16.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/AGENTS.md +2 -2
- package/GETTING_STARTED.md +1 -1
- package/PERSONA.md +4 -4
- package/README.md +11 -11
- package/atris/skills/copy-editor/SKILL.md +30 -4
- package/atris/skills/improve/SKILL.md +18 -20
- package/atris/wiki/concepts/agent-activation-contract.md +5 -3
- package/atris/wiki/concepts/workspace-initialization-contract.md +4 -4
- package/atris/wiki/index.md +1 -0
- package/ax +522 -73
- package/bin/atris.js +32 -31
- package/commands/align.js +0 -14
- package/commands/apps.js +102 -1
- package/commands/autopilot.js +197 -22
- package/commands/brain.js +219 -34
- package/commands/brainstorm.js +0 -829
- package/commands/computer.js +45 -83
- package/commands/improve.js +501 -0
- package/commands/integrations.js +228 -0
- package/commands/lesson.js +44 -0
- package/commands/member.js +4498 -226
- package/commands/mission.js +302 -27
- package/commands/now.js +89 -1
- package/commands/radar.js +181 -56
- package/commands/skill.js +37 -6
- package/commands/soul.js +0 -4
- package/commands/task.js +5582 -517
- package/commands/terminal.js +14 -10
- package/commands/wiki.js +87 -1
- package/commands/workflow.js +288 -73
- package/commands/worktree.js +52 -15
- package/commands/xp.js +41 -65
- package/lib/auto-accept-certified.js +294 -0
- package/lib/file-ops.js +0 -184
- package/lib/member-alive.js +232 -0
- package/lib/policy-lessons.js +280 -0
- package/lib/receipt-evidence.js +64 -0
- package/lib/state-detection.js +34 -0
- package/lib/task-db.js +568 -16
- package/lib/task-proof.js +43 -0
- package/package.json +1 -1
- package/utils/auth.js +13 -4
- package/commands/research.js +0 -52
- package/lib/section-merge.js +0 -196
package/commands/brain.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const crypto = require('crypto');
|
|
4
|
+
const { spawnSync } = require('child_process');
|
|
4
5
|
const { refreshNowFile } = require('./now');
|
|
5
6
|
|
|
6
7
|
const GENERATED_START = '<!-- ATRIS_BRAIN_COMPILE:START -->';
|
|
@@ -18,6 +19,39 @@ const OPTIONAL_LOAD_ORDER_FILES = [
|
|
|
18
19
|
'atris/TODO.md',
|
|
19
20
|
'atris/wiki/index.md',
|
|
20
21
|
];
|
|
22
|
+
const CORE_STATE_FILES = [
|
|
23
|
+
'events.jsonl',
|
|
24
|
+
'episodes.jsonl',
|
|
25
|
+
'task_episodes.jsonl',
|
|
26
|
+
'scorecards.jsonl',
|
|
27
|
+
'agent_tasks.jsonl',
|
|
28
|
+
'agent_mail.jsonl',
|
|
29
|
+
'agent_inboxes.jsonl',
|
|
30
|
+
'agents.jsonl',
|
|
31
|
+
'approvals.jsonl',
|
|
32
|
+
];
|
|
33
|
+
const LOOP_HEALTH_CHANNELS = [
|
|
34
|
+
{ label: 'Task plane', files: ['task_events.jsonl', 'tasks.projection.json'] },
|
|
35
|
+
{ label: 'Overnight RL', files: ['overnight_rl_self_heal.jsonl'] },
|
|
36
|
+
{ label: 'Career XP', files: ['career_xp_receipts.jsonl', 'career_xp.projection.json', 'gm_xp.projection.json'] },
|
|
37
|
+
{ label: 'Master loop', files: ['master_loop_events.jsonl'] },
|
|
38
|
+
{ label: 'Missions', files: ['mission_events.jsonl', 'missions.jsonl'] },
|
|
39
|
+
{ label: 'Company YC', files: ['company_yc_wow_events.jsonl', 'company_yc_wow_latest.json'] },
|
|
40
|
+
{ label: 'Codex goal', files: ['codex_goal.json'] },
|
|
41
|
+
{ label: 'Pulse AGI', files: ['pulse_agi_loop_receipts.jsonl'] },
|
|
42
|
+
];
|
|
43
|
+
const TIMESTAMP_KEYS = new Set([
|
|
44
|
+
'at',
|
|
45
|
+
'created_at',
|
|
46
|
+
'date',
|
|
47
|
+
'generated_at',
|
|
48
|
+
'last_checked_at',
|
|
49
|
+
'started_at',
|
|
50
|
+
'synced_at',
|
|
51
|
+
'timestamp',
|
|
52
|
+
'ts',
|
|
53
|
+
'updated_at',
|
|
54
|
+
]);
|
|
21
55
|
|
|
22
56
|
function parseArgs(args) {
|
|
23
57
|
const options = {
|
|
@@ -142,6 +176,60 @@ function readJsonlStats(filePath) {
|
|
|
142
176
|
};
|
|
143
177
|
}
|
|
144
178
|
|
|
179
|
+
function latestTimestampFromValue(value, depth = 0) {
|
|
180
|
+
if (depth > 5 || value == null) return null;
|
|
181
|
+
if (Array.isArray(value)) {
|
|
182
|
+
return value
|
|
183
|
+
.map(item => latestTimestampFromValue(item, depth + 1))
|
|
184
|
+
.filter(Boolean)
|
|
185
|
+
.sort()
|
|
186
|
+
.pop() || null;
|
|
187
|
+
}
|
|
188
|
+
if (typeof value !== 'object') return null;
|
|
189
|
+
|
|
190
|
+
let latest = null;
|
|
191
|
+
for (const [key, child] of Object.entries(value)) {
|
|
192
|
+
if (TIMESTAMP_KEYS.has(key) && (typeof child === 'string' || typeof child === 'number')) {
|
|
193
|
+
const ts = String(child);
|
|
194
|
+
if (!latest || ts > latest) latest = ts;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const childTs = latestTimestampFromValue(child, depth + 1);
|
|
198
|
+
if (childTs && (!latest || childTs > latest)) latest = childTs;
|
|
199
|
+
}
|
|
200
|
+
return latest;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function readJsonStats(filePath) {
|
|
204
|
+
if (!fs.existsSync(filePath)) {
|
|
205
|
+
return { path: filePath, exists: false, rows: 0, validRows: 0, latestTs: null };
|
|
206
|
+
}
|
|
207
|
+
const parsed = readJson(filePath);
|
|
208
|
+
return {
|
|
209
|
+
path: filePath,
|
|
210
|
+
exists: true,
|
|
211
|
+
rows: 1,
|
|
212
|
+
validRows: parsed === null ? 0 : 1,
|
|
213
|
+
latestTs: latestTimestampFromValue(parsed),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function readStateFileStats(filePath) {
|
|
218
|
+
if (filePath.endsWith('.jsonl')) return readJsonlStats(filePath);
|
|
219
|
+
if (filePath.endsWith('.json')) return readJsonStats(filePath);
|
|
220
|
+
return { path: filePath, exists: fs.existsSync(filePath), rows: 0, validRows: 0, latestTs: null };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function collectStateFileStats(stateDir) {
|
|
224
|
+
const names = new Set(CORE_STATE_FILES);
|
|
225
|
+
if (fs.existsSync(stateDir)) {
|
|
226
|
+
for (const name of fs.readdirSync(stateDir).sort()) {
|
|
227
|
+
if (name.endsWith('.json') || name.endsWith('.jsonl')) names.add(name);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return Array.from(names).map(name => readStateFileStats(path.join(stateDir, name)));
|
|
231
|
+
}
|
|
232
|
+
|
|
145
233
|
function readJsonlRows(filePath) {
|
|
146
234
|
const text = readText(filePath);
|
|
147
235
|
const rows = [];
|
|
@@ -156,6 +244,56 @@ function readJsonlRows(filePath) {
|
|
|
156
244
|
return rows;
|
|
157
245
|
}
|
|
158
246
|
|
|
247
|
+
function parseGitWorktrees(text) {
|
|
248
|
+
const out = [];
|
|
249
|
+
let current = {};
|
|
250
|
+
for (const raw of `${text || ''}\n`.split(/\r?\n/)) {
|
|
251
|
+
const line = raw.trim();
|
|
252
|
+
if (!line) {
|
|
253
|
+
if (current.worktree) out.push(path.resolve(current.worktree));
|
|
254
|
+
current = {};
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const idx = line.indexOf(' ');
|
|
258
|
+
if (idx === -1) {
|
|
259
|
+
current[line] = true;
|
|
260
|
+
} else {
|
|
261
|
+
current[line.slice(0, idx)] = line.slice(idx + 1);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function primaryWorktreeRoot(root) {
|
|
268
|
+
const result = spawnSync('git', ['worktree', 'list', '--porcelain'], {
|
|
269
|
+
cwd: root,
|
|
270
|
+
encoding: 'utf8',
|
|
271
|
+
});
|
|
272
|
+
if (result.status !== 0) return null;
|
|
273
|
+
const [primary] = parseGitWorktrees(result.stdout);
|
|
274
|
+
return primary || null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function stateRowCount(stateDir) {
|
|
278
|
+
return collectStateFileStats(stateDir)
|
|
279
|
+
.reduce((sum, item) => sum + item.rows, 0);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function resolveStateRoots(root) {
|
|
283
|
+
const primary = primaryWorktreeRoot(root);
|
|
284
|
+
if (!primary || path.resolve(primary) === path.resolve(root)) return [root];
|
|
285
|
+
|
|
286
|
+
const primaryStateDir = path.join(primary, '.atris', 'state');
|
|
287
|
+
if (!fs.existsSync(primaryStateDir)) return [root];
|
|
288
|
+
|
|
289
|
+
return stateRowCount(primaryStateDir) > 0 ? [root, primary] : [root];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function resolveStateRoot(root) {
|
|
293
|
+
const roots = resolveStateRoots(root);
|
|
294
|
+
return roots[roots.length - 1] || root;
|
|
295
|
+
}
|
|
296
|
+
|
|
159
297
|
function countTodoItems(todoText) {
|
|
160
298
|
const text = String(todoText || '');
|
|
161
299
|
const hasRenderedSections = /^##\s+(Backlog|In Progress|Blocked|Completed)\s*$/m.test(text);
|
|
@@ -297,7 +435,9 @@ function isNextMoveScorecard(row) {
|
|
|
297
435
|
|
|
298
436
|
function collectState(root) {
|
|
299
437
|
const atrisDir = path.join(root, 'atris');
|
|
300
|
-
const
|
|
438
|
+
const stateRoot = resolveStateRoot(root);
|
|
439
|
+
const stateRoots = resolveStateRoots(root);
|
|
440
|
+
const stateDirs = stateRoots.map(item => path.join(item, '.atris', 'state'));
|
|
301
441
|
const business = readJson(path.join(root, '.atris', 'business.json')) || {};
|
|
302
442
|
const todoText = readText(path.join(atrisDir, 'TODO.md'));
|
|
303
443
|
const mapText = readText(path.join(atrisDir, 'MAP.md'));
|
|
@@ -305,21 +445,11 @@ function collectState(root) {
|
|
|
305
445
|
const wikiStatus = readText(path.join(atrisDir, 'wiki', 'STATUS.md'));
|
|
306
446
|
const status = readText(path.join(atrisDir, 'STATUS.md'));
|
|
307
447
|
|
|
308
|
-
const stateFiles =
|
|
309
|
-
'events.jsonl',
|
|
310
|
-
'episodes.jsonl',
|
|
311
|
-
'task_episodes.jsonl',
|
|
312
|
-
'scorecards.jsonl',
|
|
313
|
-
'agent_tasks.jsonl',
|
|
314
|
-
'agent_mail.jsonl',
|
|
315
|
-
'agent_inboxes.jsonl',
|
|
316
|
-
'agents.jsonl',
|
|
317
|
-
'approvals.jsonl',
|
|
318
|
-
].map(name => readJsonlStats(path.join(stateDir, name)));
|
|
448
|
+
const stateFiles = stateDirs.flatMap(stateDir => collectStateFileStats(stateDir));
|
|
319
449
|
|
|
320
450
|
const totalRows = stateFiles.reduce((sum, item) => sum + item.rows, 0);
|
|
321
451
|
const validRows = stateFiles.reduce((sum, item) => sum + item.validRows, 0);
|
|
322
|
-
const latestScorecard = readJsonlRows(path.join(stateDir, 'scorecards.jsonl'))
|
|
452
|
+
const latestScorecard = stateDirs.flatMap(stateDir => readJsonlRows(path.join(stateDir, 'scorecards.jsonl')))
|
|
323
453
|
.filter(isNextMoveScorecard)
|
|
324
454
|
.sort((a, b) => scorecardTs(a).localeCompare(scorecardTs(b)))
|
|
325
455
|
.pop() || null;
|
|
@@ -344,6 +474,9 @@ function collectState(root) {
|
|
|
344
474
|
mapLineCount: mapText ? mapText.split('\n').length : 0,
|
|
345
475
|
wikiPages: listMarkdown(root, 'atris/wiki', 20),
|
|
346
476
|
stateFiles,
|
|
477
|
+
stateRoot,
|
|
478
|
+
stateRoots,
|
|
479
|
+
loopHealth: buildLoopHealth(stateFiles),
|
|
347
480
|
totalRows,
|
|
348
481
|
validRows,
|
|
349
482
|
latestScorecard: latestScorecard ? {
|
|
@@ -368,14 +501,46 @@ function countStateRows(state, names) {
|
|
|
368
501
|
.reduce((sum, item) => sum + item.rows, 0);
|
|
369
502
|
}
|
|
370
503
|
|
|
504
|
+
function stateFilesForNames(stateFiles, names) {
|
|
505
|
+
const wanted = new Set(names);
|
|
506
|
+
return stateFiles.filter(item => wanted.has(path.basename(item.path)));
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function buildLoopHealth(stateFiles) {
|
|
510
|
+
return LOOP_HEALTH_CHANNELS.map(channel => {
|
|
511
|
+
const files = stateFilesForNames(stateFiles, channel.files);
|
|
512
|
+
const rows = files.reduce((sum, item) => sum + item.rows, 0);
|
|
513
|
+
const validRows = files.reduce((sum, item) => sum + item.validRows, 0);
|
|
514
|
+
const latestTs = files
|
|
515
|
+
.map(item => item.latestTs)
|
|
516
|
+
.filter(Boolean)
|
|
517
|
+
.sort()
|
|
518
|
+
.pop() || null;
|
|
519
|
+
return {
|
|
520
|
+
label: channel.label,
|
|
521
|
+
files: channel.files,
|
|
522
|
+
rows,
|
|
523
|
+
validRows,
|
|
524
|
+
latestTs,
|
|
525
|
+
active: validRows > 0,
|
|
526
|
+
};
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
371
530
|
function strongestSignal(state) {
|
|
372
531
|
const mail = countStateRows(state, 'agent_mail.jsonl');
|
|
373
532
|
const tasks = countStateRows(state, 'agent_tasks.jsonl');
|
|
374
533
|
const scorecards = countStateRows(state, 'scorecards.jsonl');
|
|
375
534
|
const episodes = countStateRows(state, ['episodes.jsonl', 'task_episodes.jsonl']);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
535
|
+
const activeLoops = (state.loopHealth || buildLoopHealth(state.stateFiles || []))
|
|
536
|
+
.filter(channel => channel.active);
|
|
537
|
+
const loopSuffix = activeLoops.length > 0
|
|
538
|
+
? ` Loop health sees ${activeLoops.length} active channel(s): ${activeLoops.map(channel => channel.label).join(', ')}.`
|
|
539
|
+
: '';
|
|
540
|
+
if (scorecards > 0 && episodes > 0) return `${scorecards} scorecard row(s) and ${episodes} episode row(s) are available for feedback-driven learning.${loopSuffix}`;
|
|
541
|
+
if (scorecards > 0) return `${scorecards} scorecard row(s) are available for outcome scoring.${loopSuffix}`;
|
|
542
|
+
if (episodes > 0) return `${episodes} episode row(s) are available; compile them into scorecards and next-action memory.${loopSuffix}`;
|
|
543
|
+
if (activeLoops.length > 0) return `Loop health sees ${activeLoops.length} active channel(s): ${activeLoops.map(channel => channel.label).join(', ')}.`;
|
|
379
544
|
if (mail > 0) return `${mail} agent-mail row(s) are available; compile them into decisions, follow-ups, and CRM memory.`;
|
|
380
545
|
if (tasks > 0) return `${tasks} agent-task row(s) are available; use them to choose the next action.`;
|
|
381
546
|
return 'Workspace has structure, but little scored state yet; first improvement is to create scorecards and episodes.';
|
|
@@ -440,10 +605,6 @@ function latestRecommendation(root) {
|
|
|
440
605
|
return nextMove(collectState(root));
|
|
441
606
|
}
|
|
442
607
|
|
|
443
|
-
function loadBrainState(root) {
|
|
444
|
-
return readJson(path.join(root, 'atris', 'brain', 'state.json')) || collectState(root);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
608
|
function normalizeMemberSlug(memberSlug) {
|
|
448
609
|
return String(memberSlug || '').toLowerCase().replace(/[^a-z0-9_-]/g, '');
|
|
449
610
|
}
|
|
@@ -917,14 +1078,18 @@ function latestTaskEpisodes(taskEpisodes) {
|
|
|
917
1078
|
|
|
918
1079
|
function recordTaskEpisodeScorecards(options) {
|
|
919
1080
|
const root = options.root;
|
|
920
|
-
const
|
|
921
|
-
const
|
|
1081
|
+
const stateRoot = resolveStateRoot(root);
|
|
1082
|
+
const stateDir = path.join(stateRoot, '.atris', 'state');
|
|
1083
|
+
const stateDirs = resolveStateRoots(root).map(item => path.join(item, '.atris', 'state'));
|
|
922
1084
|
const scorecardsPath = path.join(stateDir, 'scorecards.jsonl');
|
|
923
|
-
const workspace =
|
|
924
|
-
|
|
1085
|
+
const workspace =
|
|
1086
|
+
readJson(path.join(stateRoot, '.atris', 'business.json')) ||
|
|
1087
|
+
readJson(path.join(root, '.atris', 'business.json')) ||
|
|
1088
|
+
{};
|
|
1089
|
+
const taskEpisodes = stateDirs.flatMap(item => readJsonlRows(path.join(item, 'task_episodes.jsonl')))
|
|
925
1090
|
.filter(row => row && row.schema === 'atris.task_episode.v1');
|
|
926
1091
|
const scoreableEpisodes = latestTaskEpisodes(taskEpisodes);
|
|
927
|
-
const existing = readJsonlRows(
|
|
1092
|
+
const existing = stateDirs.flatMap(item => readJsonlRows(path.join(item, 'scorecards.jsonl')));
|
|
928
1093
|
const seenEpisodeIds = new Set(existing
|
|
929
1094
|
.map(row => row.source_episode_id)
|
|
930
1095
|
.filter(Boolean));
|
|
@@ -940,6 +1105,7 @@ function recordTaskEpisodeScorecards(options) {
|
|
|
940
1105
|
}
|
|
941
1106
|
|
|
942
1107
|
return {
|
|
1108
|
+
stateRoot,
|
|
943
1109
|
taskEpisodes: taskEpisodes.length,
|
|
944
1110
|
written: written.length,
|
|
945
1111
|
scorecards: written,
|
|
@@ -947,11 +1113,11 @@ function recordTaskEpisodeScorecards(options) {
|
|
|
947
1113
|
}
|
|
948
1114
|
|
|
949
1115
|
function verifyTaskEpisodeScorecards(root) {
|
|
950
|
-
const
|
|
951
|
-
const taskEpisodes = readJsonlRows(path.join(
|
|
1116
|
+
const stateDirs = resolveStateRoots(root).map(item => path.join(item, '.atris', 'state'));
|
|
1117
|
+
const taskEpisodes = stateDirs.flatMap(item => readJsonlRows(path.join(item, 'task_episodes.jsonl')))
|
|
952
1118
|
.filter(row => row && row.schema === 'atris.task_episode.v1');
|
|
953
1119
|
const scoreableEpisodes = latestTaskEpisodes(taskEpisodes);
|
|
954
|
-
const scorecards = readJsonlRows(path.join(
|
|
1120
|
+
const scorecards = stateDirs.flatMap(item => readJsonlRows(path.join(item, 'scorecards.jsonl')));
|
|
955
1121
|
const scorecardEpisodeIds = new Set(scorecards
|
|
956
1122
|
.map(row => row.source_episode_id)
|
|
957
1123
|
.filter(Boolean));
|
|
@@ -997,20 +1163,39 @@ function renderBulletedLoadOrder(state) {
|
|
|
997
1163
|
.join('\n');
|
|
998
1164
|
}
|
|
999
1165
|
|
|
1166
|
+
function renderLoopHealthPanel(state) {
|
|
1167
|
+
const rows = (state.loopHealth || []).map(channel => {
|
|
1168
|
+
const status = channel.active ? 'active' : 'missing';
|
|
1169
|
+
return `| ${channel.label} | ${status} | ${channel.rows} | ${channel.validRows} | ${channel.latestTs || ''} | \`${channel.files.join('`, `')}\` |`;
|
|
1170
|
+
}).join('\n');
|
|
1171
|
+
|
|
1172
|
+
return `## Loop Health
|
|
1173
|
+
|
|
1174
|
+
| Channel | Status | Rows | Valid | Latest timestamp | Files |
|
|
1175
|
+
|---|---|---:|---:|---|---|
|
|
1176
|
+
${rows}`;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1000
1179
|
function renderStatus(state) {
|
|
1180
|
+
const stateRootLine = state.stateRoot && path.resolve(state.stateRoot) !== path.resolve(state.root)
|
|
1181
|
+
? `- State root: ${state.stateRoot} (primary checkout)\n`
|
|
1182
|
+
: '';
|
|
1183
|
+
|
|
1001
1184
|
return `# Atris Brain Status
|
|
1002
1185
|
|
|
1003
1186
|
- Generated: ${state.generatedAt}
|
|
1004
1187
|
- Workspace: ${state.name}
|
|
1005
1188
|
- Slug: ${state.slug}
|
|
1006
1189
|
- Root: ${state.root}
|
|
1007
|
-
- Now loaded: ${state.hasNow ? `yes (${state.nowHeading || 'no heading'})` : 'no'}
|
|
1190
|
+
${stateRootLine}- Now loaded: ${state.hasNow ? `yes (${state.nowHeading || 'no heading'})` : 'no'}
|
|
1008
1191
|
- MAP loaded: ${state.hasMap ? `yes (${state.mapLineCount} lines)` : 'no'}
|
|
1009
1192
|
- Wiki status loaded: ${state.hasWikiStatus ? 'yes' : 'no'}
|
|
1010
1193
|
- TODO open estimate: ${state.todo.open}
|
|
1011
|
-
- State rows: ${state.totalRows} raw / ${state.validRows} valid
|
|
1194
|
+
- State rows: ${state.totalRows} raw / ${state.validRows} valid state rows
|
|
1012
1195
|
- Latest state timestamp: ${state.latestStateTs || 'none found'}
|
|
1013
1196
|
|
|
1197
|
+
${renderLoopHealthPanel(state)}
|
|
1198
|
+
|
|
1014
1199
|
## What Improved
|
|
1015
1200
|
|
|
1016
1201
|
This run compiled scattered workspace state into one loadable brain:
|
|
@@ -1043,7 +1228,7 @@ Definitions: operator = current person or agent; move = one concrete high-levera
|
|
|
1043
1228
|
|
|
1044
1229
|
function renderLedger(state) {
|
|
1045
1230
|
const rows = state.stateFiles.map(item => {
|
|
1046
|
-
const rel = path.relative(state.root, item.path).replace(/\\/g, '/');
|
|
1231
|
+
const rel = path.relative(state.stateRoot || state.root, item.path).replace(/\\/g, '/');
|
|
1047
1232
|
return `| \`${rel}\` | ${item.exists ? 'yes' : 'no'} | ${item.rows} | ${item.validRows} | ${item.latestTs || ''} |`;
|
|
1048
1233
|
}).join('\n');
|
|
1049
1234
|
|
|
@@ -1059,7 +1244,7 @@ This is not model-weight improvement yet. It is workspace-policy and context imp
|
|
|
1059
1244
|
|
|
1060
1245
|
## Current State Inputs
|
|
1061
1246
|
|
|
1062
|
-
| Source | Exists | Rows | Valid JSONL | Latest timestamp |
|
|
1247
|
+
| Source | Exists | Rows | Valid JSON/JSONL | Latest timestamp |
|
|
1063
1248
|
|---|---:|---:|---:|---|
|
|
1064
1249
|
${rows}
|
|
1065
1250
|
|
|
@@ -1092,7 +1277,7 @@ function generatedBootBlock(state) {
|
|
|
1092
1277
|
This workspace has a compiled agent brain.
|
|
1093
1278
|
|
|
1094
1279
|
On session start, activate it first:
|
|
1095
|
-
\`atris brain activate --root
|
|
1280
|
+
\`atris brain activate --root . --verify\`
|
|
1096
1281
|
|
|
1097
1282
|
Load these first:
|
|
1098
1283
|
${renderBulletedLoadOrder(state)}
|
|
@@ -1103,7 +1288,7 @@ Shape: \`<operator>, today is about <move>\` -> \`I picked this because <why now
|
|
|
1103
1288
|
Definitions: operator = current person or agent; move = one concrete high-leverage workflow; why now = business reason; ready = prepared action or proof; paths = 2-4 optional deeper views.
|
|
1104
1289
|
|
|
1105
1290
|
Re-run after meaningful work:
|
|
1106
|
-
\`atris brain compile --root
|
|
1291
|
+
\`atris brain compile --root .\`
|
|
1107
1292
|
${GENERATED_END}
|
|
1108
1293
|
`;
|
|
1109
1294
|
}
|