atris 3.57.3 → 3.58.5
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 +12 -1
- package/atris/skills/clawhub/member-runtime/SKILL.md +9 -9
- package/atris/skills/create-member/SKILL.md +16 -13
- package/atris/skills/design/SKILL.md +27 -4
- package/atris/skills/engines/SKILL.md +57 -13
- package/atris/skills/x-search/SKILL.md +13 -5
- package/atris/skills/youtube/SKILL.md +39 -8
- package/atris/team/brainstormer/MEMBER.md +2 -2
- package/atris/team/executor/MEMBER.md +3 -3
- package/atris/team/launcher/MEMBER.md +4 -4
- package/atris/team/navigator/MEMBER.md +3 -3
- package/atris/team/researcher/MEMBER.md +2 -2
- package/atris/team/validator/MEMBER.md +1 -1
- package/atris.md +14 -0
- package/ax +157 -24
- package/bin/atris.js +79 -31
- package/commands/aeo.js +4 -4
- package/commands/agents.js +1 -1
- package/commands/align.js +12 -12
- package/commands/analytics.js +3 -3
- package/commands/app.js +5 -5
- package/commands/ask.js +175 -0
- package/commands/auth.js +7 -7
- package/commands/autoland.js +29 -5
- package/commands/autopilot-front.js +6 -6
- package/commands/autopilot.js +90 -90
- package/commands/avail.js +5 -5
- package/commands/bench.js +63 -1
- package/commands/browse.js +2 -2
- package/commands/business.js +12 -12
- package/commands/card.js +2 -2
- package/commands/clean.js +13 -13
- package/commands/close.js +297 -15
- package/commands/compile.js +13 -13
- package/commands/computer.js +94 -27
- package/commands/console.js +5 -5
- package/commands/decide.js +1 -1
- package/commands/deck.js +9 -9
- package/commands/drive.js +4 -4
- package/commands/engine.js +173 -19
- package/commands/errors.js +3 -3
- package/commands/experiments.js +18 -1
- package/commands/feed.js +2 -2
- package/commands/feedback.js +4 -4
- package/commands/fleet.js +12 -12
- package/commands/game.js +1 -1
- package/commands/guide.js +49 -0
- package/commands/improve.js +19 -17
- package/commands/init.js +67 -19
- package/commands/interview.js +7 -7
- package/commands/land.js +40 -15
- package/commands/learn.js +12 -12
- package/commands/lesson.js +2 -2
- package/commands/log.js +1 -1
- package/commands/loops.js +4 -4
- package/commands/member.js +75 -50
- package/commands/mission.js +97 -98
- package/commands/one-lap.js +1 -1
- package/commands/pack.js +74 -8
- package/commands/plugin.js +6 -6
- package/commands/probe.js +9 -9
- package/commands/pull.js +35 -35
- package/commands/pulse.js +1 -1
- package/commands/push.js +21 -21
- package/commands/rainmaker.js +1 -1
- package/commands/recap.js +7 -7
- package/commands/reel.js +2 -2
- package/commands/release.js +3 -3
- package/commands/report.js +1 -1
- package/commands/review.js +5 -5
- package/commands/revisions.js +1 -1
- package/commands/run.js +1 -1
- package/commands/scout.js +3 -3
- package/commands/security-review.js +7 -7
- package/commands/serve.js +9 -9
- package/commands/setup.js +1 -1
- package/commands/sign.js +4 -4
- package/commands/signup.js +4 -4
- package/commands/site.js +8 -3
- package/commands/skill.js +6 -6
- package/commands/slop.js +18 -18
- package/commands/social.js +3 -3
- package/commands/soul.js +14 -14
- package/commands/spaceship.js +1 -1
- package/commands/status.js +2 -2
- package/commands/strings.js +13 -13
- package/commands/study.js +4 -4
- package/commands/sync.js +8 -8
- package/commands/task.js +50 -25
- package/commands/teach.js +2 -2
- package/commands/team.js +1 -1
- package/commands/theme.js +2 -2
- package/commands/tree.js +34 -0
- package/commands/truth.js +7 -7
- package/commands/verify.js +12 -12
- package/commands/visualize.js +2 -2
- package/commands/workflow.js +97 -40
- package/commands/worktree.js +57 -1
- package/commands/write.js +9 -9
- package/commands/x-search.js +304 -15
- package/commands/xp.js +6 -3
- package/commands/youtube.js +916 -65
- package/lib/accept-verify-gate.js +3 -3
- package/lib/activity-stream.js +1 -1
- package/lib/apply-gate.js +13 -0
- package/lib/auto-accept-certified.js +28 -12
- package/lib/autoland.js +6 -6
- package/lib/bench/engines.js +59 -8
- package/lib/bench/report.js +1 -1
- package/lib/bench/runner.js +204 -5
- package/lib/bench/tree-render.js +76 -0
- package/lib/card.js +1 -1
- package/lib/chat-log-scan.js +1 -1
- package/lib/claude-boot-block.js +2 -0
- package/lib/deck-compose.js +1 -1
- package/lib/deck-history.js +2 -2
- package/lib/deck-layout.js +1 -1
- package/lib/deck-review.js +5 -5
- package/lib/deck-schema.js +1 -1
- package/lib/default-verifier.js +1 -1
- package/lib/developer-api.js +3 -0
- package/lib/engine-ask.js +66 -9
- package/lib/engine-registry.js +15 -2
- package/lib/file-ops.js +1 -1
- package/lib/fleet.js +71 -35
- package/lib/html-render.js +1 -1
- package/lib/intents.js +172 -0
- package/lib/journal.js +1 -1
- package/lib/known-commands.js +2 -2
- package/lib/land-green.js +364 -0
- package/lib/lesson-contradiction.js +2 -2
- package/lib/lesson-preflight.js +1 -1
- package/lib/manifest.js +5 -5
- package/lib/member-alive.js +9 -5
- package/lib/memory-view.js +3 -3
- package/lib/mission-protected-lane.js +1 -1
- package/lib/mission-root.js +2 -2
- package/lib/orb-context.js +10 -10
- package/lib/pack-capabilities.js +861 -3
- package/lib/permission-grants.js +2 -2
- package/lib/policy-lessons.js +6 -6
- package/lib/pulse.js +8 -8
- package/lib/receipt-evidence.js +1 -1
- package/lib/reel.js +1 -1
- package/lib/review-integrity.js +1 -1
- package/lib/runner-command.js +35 -5
- package/lib/scorecard.js +4 -4
- package/lib/security-scan.js +5 -5
- package/lib/self-drive.js +1 -1
- package/lib/site-publish.js +372 -0
- package/lib/site.js +1 -1
- package/lib/slides-deck.js +2 -2
- package/lib/state-detection.js +2 -2
- package/lib/sync-telemetry.js +2 -2
- package/lib/task-db.js +17 -10
- package/lib/task-explanation.js +1 -1
- package/lib/task-proof.js +2 -2
- package/lib/task-receipt.js +3 -3
- package/lib/theme.js +12 -12
- package/lib/todo-fallback.js +3 -3
- package/lib/todo-sections.js +1 -1
- package/lib/tree-hash.js +79 -0
- package/lib/usage.js +1 -1
- package/lib/wish-delegate.js +1 -1
- package/lib/workspace-safety.js +4 -4
- package/lib/workspace-scaffold.js +3 -3
- package/package.json +1 -1
- package/scripts/det/concierge-bakeoff.sh +26 -0
- package/scripts/det/ytquote-repair.js +0 -1
- package/scripts/det/ytrail-race.js +0 -5
- package/scripts/member-operate.mjs +52 -14
- package/scripts/outbound-artifact-gate.js +0 -3
- package/utils/auth.js +0 -3
- package/utils/config.js +0 -1
- package/scripts/det/checklist-score.js +0 -191
package/commands/avail.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Booking availability
|
|
4
|
+
* Booking availability: read/update the windows that power /book/{username}.
|
|
5
5
|
*
|
|
6
6
|
* atris avail # show current settings
|
|
7
7
|
* atris avail set --wake 2:30pm --sleep 9pm --where Ibiza --days all --apply
|
|
@@ -172,13 +172,13 @@ function summarizeHours(availableHours) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// The booking link is the funnel: an operator shares /book/{username} so a
|
|
175
|
-
// stranger can pick a slot. With no claimed handle there is no link
|
|
175
|
+
// stranger can pick a slot. With no claimed handle there is no link, say so and
|
|
176
176
|
// name the fix instead of silently dropping the line.
|
|
177
177
|
function formatBookingLink(username, appBase) {
|
|
178
178
|
const handle = String(username || '').trim();
|
|
179
179
|
const base = String(appBase || '').replace(/\/+$/, '');
|
|
180
180
|
if (!handle) {
|
|
181
|
-
return ' link: none yet
|
|
181
|
+
return ' link: none yet, claim a handle with `atris signup` to get your /book link';
|
|
182
182
|
}
|
|
183
183
|
return ` link: ${base}/book/${handle}`;
|
|
184
184
|
}
|
|
@@ -263,7 +263,7 @@ async function setAvail(argv) {
|
|
|
263
263
|
console.log(summarizeHours(payload.available_hours));
|
|
264
264
|
|
|
265
265
|
if (!opts.apply) {
|
|
266
|
-
console.log('\n Dry run
|
|
266
|
+
console.log('\n Dry run, add --apply to push to your profile.');
|
|
267
267
|
return 0;
|
|
268
268
|
}
|
|
269
269
|
|
|
@@ -308,7 +308,7 @@ async function slotsAvail(argv) {
|
|
|
308
308
|
if (!username) {
|
|
309
309
|
const identity = await apiRequestJson('/identity/me', { method: 'GET', token });
|
|
310
310
|
if (!identity.ok || !identity.data?.username) {
|
|
311
|
-
console.error('Could not resolve username
|
|
311
|
+
console.error('Could not resolve username, pass --user keshav');
|
|
312
312
|
return 1;
|
|
313
313
|
}
|
|
314
314
|
username = identity.data.username;
|
package/commands/bench.js
CHANGED
|
@@ -8,9 +8,11 @@ const {
|
|
|
8
8
|
packMetadata,
|
|
9
9
|
readResultRecords,
|
|
10
10
|
runBench,
|
|
11
|
+
runBenchPair,
|
|
11
12
|
taskMetadata,
|
|
12
13
|
} = require('../lib/bench/runner');
|
|
13
14
|
const { buildBenchReport, renderBenchReportText } = require('../lib/bench/report');
|
|
15
|
+
const { materializeCandidate } = require('../lib/bench/tree-render');
|
|
14
16
|
const { hasFlag } = require('../lib/arg-parser');
|
|
15
17
|
|
|
16
18
|
function isAtrisCliRepo(cwd = process.cwd()) {
|
|
@@ -51,16 +53,32 @@ function readRepeatedFlag(args, name) {
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
function printHelp() {
|
|
54
|
-
console.log('Usage: atris bench run [--pack <id>] [--engine <name>] [--task <id> ...] [--label baseline|candidate] [--experiment <id>] [--update-baseline] [--json]');
|
|
56
|
+
console.log('Usage: atris bench run [--pack <id>] [--engine <name>] [--model <id>] [--task <id> ...] [--label baseline|candidate] [--experiment <id>] [--update-baseline] [--json]');
|
|
57
|
+
console.log('Usage: atris bench pair --candidate <dir|git-ref> [--pack <id>] [--engine <name>] [--model <id>] [--task <id> ...] [--min-win-margin <n>] [--repeats <n>] [--current <dir>] [--json]');
|
|
55
58
|
console.log('Usage: atris bench results [--last N] [--json]');
|
|
56
59
|
console.log('Usage: atris bench tasks [--pack <id>] [--json]');
|
|
57
60
|
console.log('Usage: atris bench packs [--json]');
|
|
58
61
|
console.log('Usage: atris bench report [--pack agents-v1] [--json]');
|
|
62
|
+
console.log('packs: core-v1, agents-v1, harness-v1');
|
|
59
63
|
console.log('');
|
|
60
64
|
console.log('Bench runs product gates and only belongs in the atris CLI repo.');
|
|
61
65
|
console.log('Pass --here to allow running outside that repo.');
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
function pairScoreText(score) {
|
|
69
|
+
if (score === null) return 'could-not-run';
|
|
70
|
+
return score === 1 ? 'pass' : 'fail';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function printPairText(record) {
|
|
74
|
+
const width = Math.max(0, ...record.tasks.map((task) => task.id.length)) + 3;
|
|
75
|
+
for (const task of record.tasks) {
|
|
76
|
+
console.log(`${task.id.padEnd(width)}current ${pairScoreText(task.current)} candidate ${pairScoreText(task.candidate)} ${task.outcome}`);
|
|
77
|
+
}
|
|
78
|
+
console.log(`wins ${record.wins} losses ${record.losses} ties ${record.ties}`);
|
|
79
|
+
console.log(`verdict: ${record.verdict}, ${record.reason}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
64
82
|
function printRunText(record) {
|
|
65
83
|
console.log(record.summary);
|
|
66
84
|
for (const task of record.tasks) {
|
|
@@ -76,6 +94,7 @@ async function runCommand(args) {
|
|
|
76
94
|
const result = await runBench({
|
|
77
95
|
pack: readInlineFirstFlag(args, '--pack') || undefined,
|
|
78
96
|
engine: readInlineFirstFlag(args, '--engine') || undefined,
|
|
97
|
+
model: readInlineFirstFlag(args, '--model') || undefined,
|
|
79
98
|
taskIds: readRepeatedFlag(args, '--task'),
|
|
80
99
|
label: readInlineFirstFlag(args, '--label'),
|
|
81
100
|
experiment: readInlineFirstFlag(args, '--experiment'),
|
|
@@ -102,6 +121,48 @@ async function runCommand(args) {
|
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
123
|
|
|
124
|
+
async function pairCommand(args) {
|
|
125
|
+
const asJson = hasFlag(args, '--json');
|
|
126
|
+
const candidateSource = readInlineFirstFlag(args, '--candidate');
|
|
127
|
+
let candidateRoot = null;
|
|
128
|
+
let removeCandidate = false;
|
|
129
|
+
try {
|
|
130
|
+
if (!candidateSource) throw new BenchInfraError('candidate is required');
|
|
131
|
+
try {
|
|
132
|
+
removeCandidate = !fs.statSync(path.resolve(candidateSource)).isDirectory();
|
|
133
|
+
} catch {
|
|
134
|
+
removeCandidate = true;
|
|
135
|
+
}
|
|
136
|
+
candidateRoot = materializeCandidate(candidateSource, process.cwd());
|
|
137
|
+
const result = await runBenchPair({
|
|
138
|
+
pack: readInlineFirstFlag(args, '--pack') || undefined,
|
|
139
|
+
engine: readInlineFirstFlag(args, '--engine') || undefined,
|
|
140
|
+
model: readInlineFirstFlag(args, '--model') || undefined,
|
|
141
|
+
taskIds: readRepeatedFlag(args, '--task'),
|
|
142
|
+
minWinMargin: readInlineFirstFlag(args, '--min-win-margin') || undefined,
|
|
143
|
+
repeats: readInlineFirstFlag(args, '--repeats') || undefined,
|
|
144
|
+
currentRoot: readInlineFirstFlag(args, '--current') || undefined,
|
|
145
|
+
candidateRoot,
|
|
146
|
+
stateRoot: process.cwd(),
|
|
147
|
+
});
|
|
148
|
+
if (asJson) console.log(JSON.stringify(result.record));
|
|
149
|
+
else printPairText(result.record);
|
|
150
|
+
return result.exitCode;
|
|
151
|
+
} catch (err) {
|
|
152
|
+
const message = err && err.message ? err.message : String(err);
|
|
153
|
+
if (asJson) {
|
|
154
|
+
console.log(JSON.stringify({ schema: 'atris.bench.error.v1', error: message }));
|
|
155
|
+
} else {
|
|
156
|
+
console.error(`atris bench: ${message}`);
|
|
157
|
+
}
|
|
158
|
+
return 2;
|
|
159
|
+
} finally {
|
|
160
|
+
if (removeCandidate && candidateRoot) {
|
|
161
|
+
fs.rmSync(candidateRoot, { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
105
166
|
function tasksCommand(args) {
|
|
106
167
|
const pack = readInlineFirstFlag(args, '--pack') || undefined;
|
|
107
168
|
const tasks = taskMetadata({ pack });
|
|
@@ -200,6 +261,7 @@ async function benchCommand(args = []) {
|
|
|
200
261
|
return 2;
|
|
201
262
|
}
|
|
202
263
|
if (subcommand === 'run') return runCommand(rest);
|
|
264
|
+
if (subcommand === 'pair') return pairCommand(rest);
|
|
203
265
|
if (subcommand === 'tasks') return tasksCommand(rest);
|
|
204
266
|
if (subcommand === 'packs') return packsCommand(rest);
|
|
205
267
|
if (subcommand === 'results') return resultsCommand(rest);
|
package/commands/browse.js
CHANGED
|
@@ -32,7 +32,7 @@ async function browseAtris() {
|
|
|
32
32
|
const result = await apiRequestJson(endpoint, { method: 'GET', token: creds.token });
|
|
33
33
|
|
|
34
34
|
if (!result.ok) {
|
|
35
|
-
// API failed
|
|
35
|
+
// API failed, try local templates
|
|
36
36
|
console.log(' API unavailable, checking local templates...');
|
|
37
37
|
const localDir = path.join(os.homedir(), '.atris', 'templates');
|
|
38
38
|
if (!fs.existsSync(localDir)) {
|
|
@@ -61,7 +61,7 @@ async function browseAtris() {
|
|
|
61
61
|
desc = meta.description || '';
|
|
62
62
|
} catch {}
|
|
63
63
|
}
|
|
64
|
-
console.log(` ${name}${desc ? '
|
|
64
|
+
console.log(` ${name}${desc ? ': ' + desc : ''}`);
|
|
65
65
|
}
|
|
66
66
|
console.log('');
|
|
67
67
|
return;
|
package/commands/business.js
CHANGED
|
@@ -58,14 +58,14 @@ function validateBusinessCreateName(name) {
|
|
|
58
58
|
return {
|
|
59
59
|
ok: false,
|
|
60
60
|
usage: BUSINESS_CREATE_USAGE,
|
|
61
|
-
detail: `Refusing to create a business named "${name}"
|
|
61
|
+
detail: `Refusing to create a business named "${name}", looks like a flag, not a name.`,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
if (isAccidentalHelpBusiness(name)) {
|
|
65
65
|
return {
|
|
66
66
|
ok: false,
|
|
67
67
|
usage: BUSINESS_CREATE_USAGE,
|
|
68
|
-
detail: `Refusing to create a business named "${name}"
|
|
68
|
+
detail: `Refusing to create a business named "${name}", looks like accidental help output, not a real business.`,
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
return { ok: true };
|
|
@@ -883,7 +883,7 @@ function collectBusinessOperatingState(cwd = process.cwd(), nowMs = Date.now())
|
|
|
883
883
|
}
|
|
884
884
|
|
|
885
885
|
function seedBusinessStarterTask(cwd, todoPath, starterAction) {
|
|
886
|
-
const title = `${starterAction.title}
|
|
886
|
+
const title = `${starterAction.title}: ${starterAction.action}`;
|
|
887
887
|
try {
|
|
888
888
|
const taskDb = require('../lib/task-db');
|
|
889
889
|
const db = taskDb.open();
|
|
@@ -1626,12 +1626,12 @@ ${stagedSources.length > 0 ? `- Local evidence files: ${stagedSources.length}` :
|
|
|
1626
1626
|
'- Before sharing the workspace, run `atris business share --write` and send the handoff.',
|
|
1627
1627
|
].filter(Boolean).join('\n') + '\n';
|
|
1628
1628
|
fs.writeFileSync(cheatSheetPath, operatorSummary, 'utf8');
|
|
1629
|
-
fs.writeFileSync(onePagerPath, operatorSummary.replace('# ', '# One Pager
|
|
1629
|
+
fs.writeFileSync(onePagerPath, operatorSummary.replace('# ', '# One Pager: '), 'utf8');
|
|
1630
1630
|
|
|
1631
1631
|
const todoPath = path.join(cwd, 'atris', 'TODO.md');
|
|
1632
1632
|
if (fs.existsSync(todoPath)) {
|
|
1633
1633
|
let todoContent = fs.readFileSync(todoPath, 'utf8');
|
|
1634
|
-
const taskLine = `- **Onboard:** ${starterAction.title}
|
|
1634
|
+
const taskLine = `- **Onboard:** ${starterAction.title}: ${starterAction.action} [execute]\n`;
|
|
1635
1635
|
const backlogMatch = todoContent.match(/^## Backlog\s*$/m);
|
|
1636
1636
|
if (backlogMatch) {
|
|
1637
1637
|
const insertAt = backlogMatch.index + backlogMatch[0].length;
|
|
@@ -1761,7 +1761,7 @@ function detectBusinessSlug(explicitSlug) {
|
|
|
1761
1761
|
async function findExistingBusinessBySlug(slug, token) {
|
|
1762
1762
|
if (!slug) return null;
|
|
1763
1763
|
|
|
1764
|
-
// Local cache first
|
|
1764
|
+
// Local cache first, no network round-trip needed.
|
|
1765
1765
|
const local = loadBusinesses();
|
|
1766
1766
|
if (local[slug]) {
|
|
1767
1767
|
return { id: local[slug].business_id, name: local[slug].name, slug, source: 'local' };
|
|
@@ -1774,7 +1774,7 @@ async function findExistingBusinessBySlug(slug, token) {
|
|
|
1774
1774
|
|
|
1775
1775
|
if (!token) return null;
|
|
1776
1776
|
|
|
1777
|
-
// Cloud lookup
|
|
1777
|
+
// Cloud lookup, covers businesses the user is a member of but hasn't added.
|
|
1778
1778
|
const direct = await apiRequestJson(`/business/by-slug/${encodeURIComponent(slug)}`, {
|
|
1779
1779
|
method: 'GET',
|
|
1780
1780
|
token,
|
|
@@ -1878,7 +1878,7 @@ async function listBusinesses(opts = {}) {
|
|
|
1878
1878
|
|
|
1879
1879
|
/**
|
|
1880
1880
|
* Walk ~/arena/atris-business/ and print a fleet status table for every
|
|
1881
|
-
* customer workspace. Pure local
|
|
1881
|
+
* customer workspace. Pure local, no API calls, no rate-limit risk.
|
|
1882
1882
|
*
|
|
1883
1883
|
* Classifies each dir as: ready, flat, unbound, nested, bare, or superseded.
|
|
1884
1884
|
*
|
|
@@ -1986,7 +1986,7 @@ function listBusinessesLocal(opts = {}) {
|
|
|
1986
1986
|
}
|
|
1987
1987
|
|
|
1988
1988
|
console.log('');
|
|
1989
|
-
console.log(`Atris Fleet
|
|
1989
|
+
console.log(`Atris Fleet: ${rootDir}`);
|
|
1990
1990
|
console.log('═'.repeat(86));
|
|
1991
1991
|
console.log(' CUSTOMER STATE FILES BIZ.JSON ATRIS/ ACTION');
|
|
1992
1992
|
console.log(' ' + '─'.repeat(83));
|
|
@@ -2016,7 +2016,7 @@ function listBusinessesLocal(opts = {}) {
|
|
|
2016
2016
|
const counts = {};
|
|
2017
2017
|
for (const c of customers) counts[c.state] = (counts[c.state] || 0) + 1;
|
|
2018
2018
|
const summary = order.filter((s) => counts[s]).map((s) => `${counts[s]} ${s}`).join(', ');
|
|
2019
|
-
console.log(` ${customers.length} customers
|
|
2019
|
+
console.log(` ${customers.length} customers: ${summary}`);
|
|
2020
2020
|
console.log('');
|
|
2021
2021
|
|
|
2022
2022
|
const needsWork = customers.filter((c) => ['flat', 'unbound', 'flat-unbound', 'nested'].includes(c.state));
|
|
@@ -3086,7 +3086,7 @@ async function connectService(connector, ...flags) {
|
|
|
3086
3086
|
for (const s of integrations) {
|
|
3087
3087
|
console.log(` ${s}`);
|
|
3088
3088
|
}
|
|
3089
|
-
if (integrations.length === 0) console.log(' (none found
|
|
3089
|
+
if (integrations.length === 0) console.log(' (none found, install skills first)');
|
|
3090
3090
|
return;
|
|
3091
3091
|
}
|
|
3092
3092
|
|
|
@@ -3540,7 +3540,7 @@ function printBusinessHelp() {
|
|
|
3540
3540
|
}
|
|
3541
3541
|
|
|
3542
3542
|
async function businessCommand(subcommand, ...args) {
|
|
3543
|
-
// Help intercept
|
|
3543
|
+
// Help intercept, without this, `atris business init --help` would treat
|
|
3544
3544
|
// `--help` as a business name and create one. Same for any subcommand that
|
|
3545
3545
|
// takes a positional name/slug.
|
|
3546
3546
|
if (!subcommand || isHelpToken(subcommand)) {
|
package/commands/card.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// atris card
|
|
1
|
+
// atris card, one line of text -> a beautiful, on-brand image (your theme).
|
|
2
2
|
//
|
|
3
3
|
// atris card "Ship faster" --kind statement --theme brand --size og
|
|
4
4
|
// atris card "It just works" --kind quote --by "a happy user"
|
|
@@ -64,7 +64,7 @@ function run(argv) {
|
|
|
64
64
|
const { flags, pos } = parseFlags(argv);
|
|
65
65
|
|
|
66
66
|
if (pos[0] === 'help' || flags.help) {
|
|
67
|
-
console.log(`\n atris card
|
|
67
|
+
console.log(`\n atris card, one line of text into an on-brand image\n
|
|
68
68
|
atris card "Your headline" [--kind statement|quote|stat] [--theme <name>] [--size og|wide|square|story]
|
|
69
69
|
flags: --sub --kicker --by --number --label --brand --version --out <file.png> --html-only\n
|
|
70
70
|
examples:
|
package/commands/clean.js
CHANGED
|
@@ -122,7 +122,7 @@ function cleanAtris(options = {}) {
|
|
|
122
122
|
if (unhealable.length > 0) {
|
|
123
123
|
console.log(`⚠ ${unhealable.length} MAP.md ${unhealable.length === 1 ? 'ref' : 'refs'} couldn't be healed:`);
|
|
124
124
|
unhealable.slice(0, 3).forEach(ref => {
|
|
125
|
-
console.log(` • ${ref.file}:${ref.line}
|
|
125
|
+
console.log(` • ${ref.file}:${ref.line}: ${ref.reason}`);
|
|
126
126
|
});
|
|
127
127
|
if (unhealable.length > 3) {
|
|
128
128
|
console.log(` ... and ${unhealable.length - 3} more`);
|
|
@@ -156,7 +156,7 @@ function cleanAtris(options = {}) {
|
|
|
156
156
|
if (stalePages.length > 0) {
|
|
157
157
|
console.log(`⚠ ${stalePages.length} stale ${stalePages.length === 1 ? 'page' : 'pages'} (source changed since last compiled):`);
|
|
158
158
|
stalePages.forEach(sp => {
|
|
159
|
-
console.log(` • ${path.relative(cwd, sp.page)}
|
|
159
|
+
console.log(` • ${path.relative(cwd, sp.page)}: stale source: ${sp.staleSource}`);
|
|
160
160
|
});
|
|
161
161
|
console.log('');
|
|
162
162
|
} else {
|
|
@@ -165,7 +165,7 @@ function cleanAtris(options = {}) {
|
|
|
165
165
|
|
|
166
166
|
// Dead code
|
|
167
167
|
if ((results.deadFiles || []).length > 0) {
|
|
168
|
-
console.log(`⚠ ${results.deadFiles.length} dead ${results.deadFiles.length === 1 ? 'file' : 'files'} (unreachable and unreferenced
|
|
168
|
+
console.log(`⚠ ${results.deadFiles.length} dead ${results.deadFiles.length === 1 ? 'file' : 'files'} (unreachable and unreferenced, atris slop dead for detail):`);
|
|
169
169
|
results.deadFiles.slice(0, 5).forEach((f) => console.log(` • ${f}`));
|
|
170
170
|
if (results.deadFiles.length > 5) console.log(` ... and ${results.deadFiles.length - 5} more`);
|
|
171
171
|
console.log('');
|
|
@@ -252,8 +252,8 @@ function firstLine(text) {
|
|
|
252
252
|
function mapScriptLine(step) {
|
|
253
253
|
const script = MAP_SCRIPTS.find(s => step.script.endsWith(s.file));
|
|
254
254
|
if (step.status === 'would_run') return `✓ ${script.dryLabel} (${step.script})`;
|
|
255
|
-
if (step.status === 'skipped') return `○ Skipped ${step.script}
|
|
256
|
-
if (step.status === 'failed') return `✗ ${script.failLabel}
|
|
255
|
+
if (step.status === 'skipped') return `○ Skipped ${step.script}: ${step.detail}`;
|
|
256
|
+
if (step.status === 'failed') return `✗ ${script.failLabel}: ${step.detail}`;
|
|
257
257
|
return `✓ ${script.ranLabel}`;
|
|
258
258
|
}
|
|
259
259
|
|
|
@@ -368,8 +368,8 @@ function healBrokenMapRefs(cwd, atrisDir, dryRun = false, homeDir = os.homedir()
|
|
|
368
368
|
|
|
369
369
|
// Match both `file.js:123` and `file.js:123-456` with surrounding context
|
|
370
370
|
// [^\S\n] = horizontal whitespace only (no newlines)
|
|
371
|
-
// Required delimiter
|
|
372
|
-
const refPattern = /(`?)([a-zA-Z0-9_~\-./\\]+\.(js|ts|py|go|rs|rb|java|c|cpp|h|hpp|md|json|yaml|yml)):(\d+)(?:-(\d+))?(`?)([^\S\n]*[\(\[
|
|
371
|
+
// Required delimiter set, including the u2014 escape, prevents bleeding into adjacent refs on same line
|
|
372
|
+
const refPattern = /(`?)([a-zA-Z0-9_~\-./\\]+\.(js|ts|py|go|rs|rb|java|c|cpp|h|hpp|md|json|yaml|yml)):(\d+)(?:-(\d+))?(`?)([^\S\n]*[\(\[\u2014\-][^\S\n]*([^)\]\n]+))?/g;
|
|
373
373
|
|
|
374
374
|
// Function Inventory form: `symbolName()` → `file:line[-line]`
|
|
375
375
|
// Pre-scan to build a (file:line) → symbol map so refs with the symbol BEFORE them still verify.
|
|
@@ -518,7 +518,7 @@ function findFunctionEnd(lines, startLine) {
|
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
/**
|
|
521
|
-
* Extract a symbol name from context like "(interactiveEntry function)" or "
|
|
521
|
+
* Extract a symbol name from context like "(interactiveEntry function)" or "Main entry" after punctuation
|
|
522
522
|
*/
|
|
523
523
|
function extractSymbol(context) {
|
|
524
524
|
if (!context) return null;
|
|
@@ -529,7 +529,7 @@ function extractSymbol(context) {
|
|
|
529
529
|
const unquoted = context.trim().replace(/`/g, '');
|
|
530
530
|
const wrapper = unquoted.match(/^([\(\[])/)?.[1];
|
|
531
531
|
let cleaned = unquoted
|
|
532
|
-
.replace(/^[\(\[
|
|
532
|
+
.replace(/^[\(\[\u2014\-:]+\s*/, '')
|
|
533
533
|
.trim();
|
|
534
534
|
if (wrapper === '(') cleaned = cleaned.replace(/\)$/, '').trim();
|
|
535
535
|
if (wrapper === '[') cleaned = cleaned.replace(/\]$/, '').trim();
|
|
@@ -553,13 +553,13 @@ function extractSymbol(context) {
|
|
|
553
553
|
|
|
554
554
|
/**
|
|
555
555
|
* Find the line number where a symbol is defined (strict patterns only)
|
|
556
|
-
* Returns null if only loose matches found
|
|
556
|
+
* Returns null if only loose matches found, prevents healing to wrong locations
|
|
557
557
|
*/
|
|
558
558
|
function findSymbolLine(fileContent, symbol) {
|
|
559
559
|
const lines = fileContent.split('\n');
|
|
560
560
|
const esc = escapeRegExp(symbol);
|
|
561
561
|
|
|
562
|
-
// Strict definition patterns only
|
|
562
|
+
// Strict definition patterns only, no loose fallback
|
|
563
563
|
const patterns = [
|
|
564
564
|
new RegExp(`^\\s*(async\\s+)?function\\s+${esc}\\s*\\(`), // function name(
|
|
565
565
|
new RegExp(`^\\s*(const|let|var)\\s+${esc}\\s*=`), // const/let/var name =
|
|
@@ -652,7 +652,7 @@ function checkPageStaleness(cwd, filePath) {
|
|
|
652
652
|
|
|
653
653
|
// Check each source's mtime against last_compiled.
|
|
654
654
|
// Source entries can include a line range and/or a parenthesized annotation,
|
|
655
|
-
// e.g. "bin/atris.js:199-340 (showHelp function)"
|
|
655
|
+
// e.g. "bin/atris.js:199-340 (showHelp function)". Strip both before stat.
|
|
656
656
|
for (const source of sources) {
|
|
657
657
|
const filePart = source
|
|
658
658
|
.replace(/\s*\([^)]*\)\s*$/, '') // drop trailing "(annotation)"
|
|
@@ -670,7 +670,7 @@ function checkPageStaleness(cwd, filePath) {
|
|
|
670
670
|
};
|
|
671
671
|
}
|
|
672
672
|
} catch {
|
|
673
|
-
// Source file doesn't exist
|
|
673
|
+
// Source file doesn't exist, that's also a staleness signal
|
|
674
674
|
return {
|
|
675
675
|
page: filePath,
|
|
676
676
|
staleSource: source + ' (missing)',
|