tonedial 0.1.0 → 0.1.2
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/dist/cli.js +5 -2
- package/dist/commands/compile.js +3 -12
- package/dist/commands/create.js +7 -7
- package/dist/commands/doctor.js +23 -16
- package/dist/commands/edit.js +10 -11
- package/dist/commands/init.js +8 -14
- package/dist/commands/save.js +5 -13
- package/dist/commands/set.js +85 -62
- package/dist/commands/show.js +20 -30
- package/dist/commands/transfer.js +0 -1
- package/dist/commands/update.js +89 -42
- package/dist/commands/use.js +6 -8
- package/dist/commands/wire.js +1 -1
- package/dist/core/anchors.js +0 -3
- package/dist/core/combos.js +6 -38
- package/dist/core/compile.js +1 -5
- package/dist/core/config.js +0 -1
- package/dist/core/i18n.js +70 -72
- package/dist/core/locales/es.js +35 -36
- package/dist/core/locales/ja.js +35 -36
- package/dist/core/locales/zh.js +35 -36
- package/dist/core/seeds.js +3 -3
- package/dist/core/selfupdate.js +47 -2
- package/dist/core/skill.js +9 -6
- package/dist/ui/format.js +5 -8
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import { runEdit } from "./commands/edit.js";
|
|
|
20
20
|
import { runUpdate } from "./commands/update.js";
|
|
21
21
|
import { runSave } from "./commands/save.js";
|
|
22
22
|
import { runCreate } from "./commands/create.js";
|
|
23
|
-
import { runAddress, runSet, runReset } from "./commands/set.js";
|
|
23
|
+
import { runAddress, runPersona, runSet, runReset } from "./commands/set.js";
|
|
24
24
|
import { runShow } from "./commands/show.js";
|
|
25
25
|
import { runUse } from "./commands/use.js";
|
|
26
26
|
import { runDoctor } from "./commands/doctor.js";
|
|
@@ -34,7 +34,7 @@ export const JSON_SCHEMA = 3;
|
|
|
34
34
|
* run time is the one thing that breaks all three binary packagers at once. A test asserts this
|
|
35
35
|
* equals the manifest, which is the cheap half of the trade.
|
|
36
36
|
*/
|
|
37
|
-
export const VERSION = "0.1.
|
|
37
|
+
export const VERSION = "0.1.2";
|
|
38
38
|
const FLAG_NAMES = ["project", "check", "explain", "global", "here", "migrateLegacy", "auto", "dryRun", "fix", "rollback", "fromOperation", "fromPreset", "restorePreset", "preset", "slug", "acceptUsage", "lang", "commands", "tools"];
|
|
39
39
|
/** Command-line spelling for each flag, where it differs from the field name. */
|
|
40
40
|
const FLAG_SPELLING = {
|
|
@@ -49,6 +49,7 @@ const COMMANDS = {
|
|
|
49
49
|
set: { run: runSet, flags: [], max: null, context: "state" },
|
|
50
50
|
test: { run: runTest, flags: ["project", "dryRun", "preset", "acceptUsage"], max: 1 },
|
|
51
51
|
address: { run: runAddress, flags: [], max: 2, context: "state" },
|
|
52
|
+
persona: { run: runPersona, flags: [], max: 2, context: "state" },
|
|
52
53
|
reset: { run: runReset, flags: [], max: 1, context: "state" },
|
|
53
54
|
show: { run: runShow, flags: ["explain"], max: 1 },
|
|
54
55
|
create: { run: runCreate, flags: ["slug", "auto", "dryRun"], max: null, context: "state" },
|
|
@@ -78,6 +79,7 @@ const COMMAND_GROUPS = [
|
|
|
78
79
|
["tone", [
|
|
79
80
|
["set", "set <axis>=<level> …"],
|
|
80
81
|
["address", "address [self user]"],
|
|
82
|
+
["persona", "persona [agent user]"],
|
|
81
83
|
["reset", "reset [axis]"],
|
|
82
84
|
["show", "show [slug]"],
|
|
83
85
|
["test", "test [claude|codex]"],
|
|
@@ -108,6 +110,7 @@ const COMMAND_EXAMPLES = {
|
|
|
108
110
|
set: ["tonedial set", "tonedial set warmth=5 critique=4", "tonedial set persona.agent=reviewer"],
|
|
109
111
|
test: ["tonedial test codex --dry-run", "tonedial test claude --project .", "tonedial test codex --preset my-tone --accept-usage"],
|
|
110
112
|
address: ['tonedial address "assistant" "friend"'],
|
|
113
|
+
persona: ["tonedial persona", 'tonedial persona "Fictional reviewer" "Developer"'],
|
|
111
114
|
reset: ["tonedial reset", "tonedial reset warmth"],
|
|
112
115
|
show: ["tonedial show", "tonedial show --explain"],
|
|
113
116
|
create: ["tonedial create", 'tonedial create "Jarvis" --slug jarvis care=3 --auto'],
|
package/dist/commands/compile.js
CHANGED
|
@@ -4,7 +4,7 @@ import { compile, measure } from "../core/compile.js";
|
|
|
4
4
|
import { ConfigError, defaultConfig, parseConfig } from "../core/config.js";
|
|
5
5
|
import { toCompileInput } from "../core/resolve.js";
|
|
6
6
|
import { contextArtifactTargets } from "../core/seeds.js";
|
|
7
|
-
import {
|
|
7
|
+
import { artifactSize, humanText, nextStep } from "../ui/format.js";
|
|
8
8
|
import { wrap } from "../ui/width.js";
|
|
9
9
|
import { confirm } from "../ui/prompt.js";
|
|
10
10
|
import { captureRawEntry, gate, planChange, rawReadChange } from "../wiring/apply.js";
|
|
@@ -60,15 +60,6 @@ export async function applyPlanned(ctx, changes, finalChanges = [], review = fal
|
|
|
60
60
|
}
|
|
61
61
|
return result;
|
|
62
62
|
}
|
|
63
|
-
export function sizeWarning(size, t) {
|
|
64
|
-
// It warns and never fails: a user is entitled to switch every axis on, and a budget that
|
|
65
|
-
// refuses to compile is a different product.
|
|
66
|
-
if (size.overCap)
|
|
67
|
-
return [t.artifact.overCap(num(size.chars), num(size.cap))];
|
|
68
|
-
if (size.overTarget)
|
|
69
|
-
return [t.artifact.overTarget(num(size.chars), num(size.target))];
|
|
70
|
-
return [];
|
|
71
|
-
}
|
|
72
63
|
export async function runCompile(ctx) {
|
|
73
64
|
const check = ctx.flags.check;
|
|
74
65
|
const { change: configChange, config } = planConfig(ctx);
|
|
@@ -113,10 +104,10 @@ export async function runCompile(ctx) {
|
|
|
113
104
|
lines: [
|
|
114
105
|
...wrap(status, ctx.ui.width - 2).map(line => ` ${ctx.ui.bold((!check || current ? ctx.ui.success : ctx.ui.warn)(line))}`),
|
|
115
106
|
` ${humanText(ctx.paths.tone)}`,
|
|
116
|
-
` ${
|
|
107
|
+
` ${ctx.ui.dim(artifactSize(size, ctx.t))}`,
|
|
117
108
|
...nextStep(check && !current ? "tonedial compile" : "tonedial show", ctx.ui),
|
|
118
109
|
],
|
|
119
110
|
json: { path: ctx.paths.tone, agentsPath: ctx.paths.agents, written: !check, ...size },
|
|
120
|
-
warnings:
|
|
111
|
+
warnings: [],
|
|
121
112
|
};
|
|
122
113
|
}
|
package/dist/commands/create.js
CHANGED
|
@@ -11,7 +11,7 @@ import { guardTerminal } from "../ui/prompt.js";
|
|
|
11
11
|
import { wrap } from "../ui/width.js";
|
|
12
12
|
import { planConfig } from "./compile.js";
|
|
13
13
|
import { savePreset } from "./save.js";
|
|
14
|
-
import { applyAssignments } from "./set.js";
|
|
14
|
+
import { applyAssignments, settingsWarnings } from "./set.js";
|
|
15
15
|
export async function runCreate(ctx, args) {
|
|
16
16
|
try {
|
|
17
17
|
const state = planConfig(ctx);
|
|
@@ -23,7 +23,7 @@ export async function runCreate(ctx, args) {
|
|
|
23
23
|
config.persona.agent ??= defaults.agent;
|
|
24
24
|
let displayName = args[0]?.trim() ?? "";
|
|
25
25
|
let slug = ctx.flags.slug ?? undefined;
|
|
26
|
-
|
|
26
|
+
applyAssignments(config, args.slice(1), ctx.t, ctx.asJson);
|
|
27
27
|
if (ctx.canPrompt && !ctx.flags.auto && !ctx.flags.dryRun) {
|
|
28
28
|
const release = guardTerminal();
|
|
29
29
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -60,10 +60,9 @@ export async function runCreate(ctx, args) {
|
|
|
60
60
|
const chosen = await ask(label, value);
|
|
61
61
|
try {
|
|
62
62
|
const candidate = structuredClone(config);
|
|
63
|
-
|
|
63
|
+
applyAssignments(candidate, [`${key}=${chosen}`], ctx.t, false);
|
|
64
64
|
serializeConfig(candidate, ctx.t);
|
|
65
65
|
Object.assign(config, candidate);
|
|
66
|
-
warnings.push(...applied.warnings);
|
|
67
66
|
if (key === "persona.user" || key === "persona.agent") {
|
|
68
67
|
process.stdout.write(` ${ctx.t.create.descriptionCount([...chosen].length, PERSONA_DESCRIPTION_MAX)}\n`);
|
|
69
68
|
}
|
|
@@ -97,9 +96,10 @@ export async function runCreate(ctx, args) {
|
|
|
97
96
|
return {
|
|
98
97
|
...result,
|
|
99
98
|
json: { ...result.json, ...(result.json.created === true ? { config: toCompileInput(config) } : {}) },
|
|
100
|
-
warnings:
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
warnings: result.json.created === true ? [
|
|
100
|
+
...settingsWarnings(config, ctx.t, ctx.asJson), ...riskWarnings(config.axes, ctx.t),
|
|
101
|
+
...checkCombos(config.axes).map((notice) => combination(notice, ctx.t)),
|
|
102
|
+
] : [],
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
catch (cause) {
|
package/dist/commands/doctor.js
CHANGED
|
@@ -7,7 +7,7 @@ import { runRebuildNative } from "./wire.js";
|
|
|
7
7
|
import { compile, measure } from "../core/compile.js";
|
|
8
8
|
import { ConfigError, defaultConfig, isConfigV2, parseConfig } from "../core/config.js";
|
|
9
9
|
import { inspectOperations, inspectRollback } from "../core/operations.js";
|
|
10
|
-
import { join } from "node:path";
|
|
10
|
+
import { join, relative } from "node:path";
|
|
11
11
|
import { AGENT_TOOLS, CONTEXT_ARTIFACT_FILENAME, CONTEXT_GUIDE_FILENAME, UPDATE_COMMAND, connectionScopeFlag, onPath, readerPath, resolveAgentPaths, shimScript, installShape, canonicalDestination, shellQuote } from "../core/paths.js";
|
|
12
12
|
import { SKILL_NAME } from "../core/skill.js";
|
|
13
13
|
import { GUIDE_FORMAT_MARKER } from "../core/reader.js";
|
|
@@ -15,7 +15,7 @@ import { inspect as inspectSkill, skillPath } from "../wiring/skill.js";
|
|
|
15
15
|
import { candidateRcPaths, pathLineState, rcPath, withPathLine } from "../wiring/shell.js";
|
|
16
16
|
import { SEED_VERSION, inspectContextLayout, inspectSeeds, recordedSeedSelection, } from "../core/seeds.js";
|
|
17
17
|
import { toCompileInput } from "../core/resolve.js";
|
|
18
|
-
import {
|
|
18
|
+
import { artifactSize, humanText, nextStep, receiptLines, recoveryRollbackLines, section } from "../ui/format.js";
|
|
19
19
|
import { wrap } from "../ui/width.js";
|
|
20
20
|
import { applyRollback, assertFresh, planChange, previewRollback } from "../wiring/apply.js";
|
|
21
21
|
import { confirm } from "../ui/prompt.js";
|
|
@@ -585,7 +585,7 @@ async function doctorReport(ctx, showRollbackCommands = true, showCodexAction =
|
|
|
585
585
|
checks.push(onDisk === null
|
|
586
586
|
? { name: "TONE.md", state: "problem", detail: ctx.t.doctor.toneNotWritten, repair: "tonedial compile" }
|
|
587
587
|
: onDisk === expected
|
|
588
|
-
? { name: "TONE.md", state: "ok", detail:
|
|
588
|
+
? { name: "TONE.md", state: "ok", detail: artifactSize(measure(expected), ctx.t) }
|
|
589
589
|
: {
|
|
590
590
|
name: "TONE.md",
|
|
591
591
|
state: "problem",
|
|
@@ -681,9 +681,11 @@ async function doctorReport(ctx, showRollbackCommands = true, showCodexAction =
|
|
|
681
681
|
const appHealthy = diagnosis.layout.kind === "current" && diagnosis.layout.cause === "none" && seeds.every(({ state }) => state === "current");
|
|
682
682
|
const lines = [
|
|
683
683
|
` ${ctx.ui.bold((appHealthy ? ctx.ui.success : ctx.ui.warn)(ctx.t.doctor.applicationHealth(appHealthy)))}`,
|
|
684
|
-
...
|
|
685
|
-
|
|
686
|
-
|
|
684
|
+
...(integrations.length || nativeAttention ? [
|
|
685
|
+
...section(ctx.t.doctor.connectionsHeading, ctx.ui),
|
|
686
|
+
...wrap(ctx.t.doctor.connectionHealth(nativeAttention), ctx.ui.width - 2).map((line) => ` ${nativeAttention ? ctx.ui.warn(line) : line}`),
|
|
687
|
+
...wrap(ctx.t.doctor.hookSettingScope, ctx.ui.width - 2).map(line => ` ${line}`),
|
|
688
|
+
] : []),
|
|
687
689
|
...section(ctx.t.doctor.checksHeading, ctx.ui),
|
|
688
690
|
...renderCheckBlocks(shownChecks, ctx.flags.verbose ? [] : hookSettings, integrations, ctx),
|
|
689
691
|
// A repair receipt presents its new IDs once in native→app order. Standalone diagnosis
|
|
@@ -753,8 +755,7 @@ async function runRollback(ctx, operationId) {
|
|
|
753
755
|
* The seeds in home against the ones this package carries.
|
|
754
756
|
*
|
|
755
757
|
* An npm update replaces the code and never touches `~/.tonedial/`, so a corrected anchor would
|
|
756
|
-
* otherwise never reach an existing user.
|
|
757
|
-
* what tells someone there is a reason to.
|
|
758
|
+
* otherwise never reach an existing user. `doctor --fix` refreshes generated application files.
|
|
758
759
|
*/
|
|
759
760
|
function seedCheck(ctx, config, seeds) {
|
|
760
761
|
// Zero means `init` never ran, which `use` and `wire` reach on their own and which nothing is
|
|
@@ -771,7 +772,7 @@ function seedCheck(ctx, config, seeds) {
|
|
|
771
772
|
state: "problem",
|
|
772
773
|
detail: ctx.t.doctor.seedsAttention,
|
|
773
774
|
files: stale.map(({ seed, state }) => ({ path: seed.path, reason: state })),
|
|
774
|
-
...(stale.every(({ state }) => state === "missing" || state === "stale") ? { repair: repairCommand(ctx, "
|
|
775
|
+
...(stale.every(({ state }) => state === "missing" || state === "stale") ? { repair: repairCommand(ctx, "doctor --fix") } : {}),
|
|
775
776
|
};
|
|
776
777
|
}
|
|
777
778
|
/** Whether the skill is linked, copied, someone else's, or simply not installed. */
|
|
@@ -1050,15 +1051,23 @@ function elsewhereReport(rows, ctx) {
|
|
|
1050
1051
|
}
|
|
1051
1052
|
function report(check, ctx) {
|
|
1052
1053
|
const paint = check.state === "problem" ? ctx.ui.error : check.state === "ok" ? ctx.ui.success : ctx.ui.dim;
|
|
1053
|
-
const head = ` ${paint(MARK[check.state])} ${ctx.ui.bold(humanText(check.name))}`;
|
|
1054
|
+
const head = ` ${paint(MARK[check.state])} ${ctx.ui.bold(humanText(check.name === "seeds" ? ctx.t.doctor.seedsHeading : check.name))}`;
|
|
1054
1055
|
// Keep the marker and check name together, then give every detail a stable four-cell hanging
|
|
1055
1056
|
// indent. A fixed name column made a narrow doctor report spend most of its width on padding.
|
|
1056
|
-
const body = (check.humanDetail ?? [check.detail]).flatMap(detail => detail.split("\n"))
|
|
1057
|
+
const body = (check.files?.length ? [] : check.humanDetail ?? [check.detail]).flatMap(detail => detail.split("\n"))
|
|
1057
1058
|
.flatMap(line => receiptLines(humanText(line), ctx.ui.width - 6));
|
|
1058
1059
|
const lines = [head, ...body.map((line) => ` ${check.state === "ok" ? ctx.ui.dim(line) : line}`)];
|
|
1059
|
-
|
|
1060
|
-
lines.push(
|
|
1061
|
-
|
|
1060
|
+
if (check.files?.length) {
|
|
1061
|
+
lines.push(` ${humanText(ctx.paths.root)}`);
|
|
1062
|
+
for (const reason of ["missing", "stale", "modified", "foreign", "unreadable"]) {
|
|
1063
|
+
const files = check.files.filter(file => file.reason === reason);
|
|
1064
|
+
if (!files.length)
|
|
1065
|
+
continue;
|
|
1066
|
+
lines.push(...wrap(ctx.t.doctor.seedReason[reason], ctx.ui.width - 6).map(line => ` ${line}`));
|
|
1067
|
+
for (const file of files) {
|
|
1068
|
+
lines.push(...wrap(humanText(relative(ctx.paths.root, file.path)), ctx.ui.width - 8).map(line => ` ${line}`));
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1062
1071
|
}
|
|
1063
1072
|
if (check.repair)
|
|
1064
1073
|
lines.push(...nextStep(check.repair, ctx.ui));
|
|
@@ -1092,7 +1101,5 @@ function unconnectedReport(settings, ctx) {
|
|
|
1092
1101
|
return [
|
|
1093
1102
|
` ${ctx.ui.dim(MARK.note)} ${ctx.ui.bold(ctx.t.doctor.hookGroupHeading)}`,
|
|
1094
1103
|
...wrap(ctx.t.doctor.hookGroupUnknown(tools), ctx.ui.width - 4).map(line => ` ${line}`),
|
|
1095
|
-
...wrap(ctx.t.doctor.hookGroupMissing, ctx.ui.width - 4).map(line => ` ${line}`),
|
|
1096
|
-
...wrap(ctx.t.doctor.hookGroupAction, ctx.ui.width - 4).map(line => ` ${line}`),
|
|
1097
1104
|
];
|
|
1098
1105
|
}
|
package/dist/commands/edit.js
CHANGED
|
@@ -6,11 +6,12 @@ import { tmpdir } from "node:os";
|
|
|
6
6
|
import { isDeepStrictEqual } from "node:util";
|
|
7
7
|
import { CONFIG_SCHEMA, ConfigError, parseConfig, serializeConfig } from "../core/config.js";
|
|
8
8
|
import { BUNDLED, SLUG_PATTERN, matchesPreset, withPreset, assertPresetSelection, customPresetDir, inspectPresetLibrary, parsePreset, preparePresetWrite, resolvePreset, } from "../core/presets.js";
|
|
9
|
-
import { applyPlanned, planArtifact, planConfig
|
|
9
|
+
import { applyPlanned, planArtifact, planConfig } from "./compile.js";
|
|
10
10
|
import { check as checkCombos } from "../core/combos.js";
|
|
11
|
-
import { combination, humanText, riskWarnings } from "../ui/format.js";
|
|
11
|
+
import { artifactSize, combination, humanText, riskWarnings } from "../ui/format.js";
|
|
12
12
|
import { captureRawEntry, planChange, rawReadChange, rawReadCheck } from "../wiring/apply.js";
|
|
13
13
|
import { emptyWiring } from "../wiring/ownership.js";
|
|
14
|
+
import { settingsWarnings } from "./set.js";
|
|
14
15
|
/**
|
|
15
16
|
* The editor to hand the file to. `$VISUAL` wins over `$EDITOR` by long convention — a user
|
|
16
17
|
* who sets both means the first for interactive work, which this is.
|
|
@@ -116,11 +117,11 @@ export async function runEdit(ctx, args) {
|
|
|
116
117
|
}
|
|
117
118
|
const { change: toneChange, size } = planArtifact(ctx, config);
|
|
118
119
|
await commit([toneChange], [{ ...baseline, after }]);
|
|
119
|
-
lines.push(` ${
|
|
120
|
+
lines.push(` ${ctx.ui.dim(artifactSize(size, ctx.t))}`);
|
|
120
121
|
return {
|
|
121
122
|
lines,
|
|
122
123
|
json: { path: target.path, editor: editor[0], opened: true, changed: true, chars: size.chars },
|
|
123
|
-
warnings: stateWarnings(ctx, config
|
|
124
|
+
warnings: stateWarnings(ctx, config),
|
|
124
125
|
};
|
|
125
126
|
}
|
|
126
127
|
// **Refused, not dropped.** `parsePreset` returns the slug it was handed and ignores the one
|
|
@@ -189,8 +190,8 @@ export async function runEdit(ctx, args) {
|
|
|
189
190
|
const { change: toneChange, size } = planArtifact(ctx, config);
|
|
190
191
|
const finalConfig = { ...configRead.change, after: serializeConfig(config, ctx.t) };
|
|
191
192
|
await commit([configRead.change, presetChange, toneChange], [finalConfig]);
|
|
192
|
-
lines.push(` ${
|
|
193
|
-
warnings.push(...stateWarnings(ctx, config
|
|
193
|
+
lines.push(` ${ctx.ui.dim(artifactSize(size, ctx.t))}`);
|
|
194
|
+
warnings.push(...stateWarnings(ctx, config));
|
|
194
195
|
}
|
|
195
196
|
else {
|
|
196
197
|
await commit([configRead.change, presetChange]);
|
|
@@ -226,13 +227,11 @@ export async function runEdit(ctx, args) {
|
|
|
226
227
|
}
|
|
227
228
|
}
|
|
228
229
|
/** The notices every other state-changing command emits, through the same owners they use. */
|
|
229
|
-
function stateWarnings(ctx, config
|
|
230
|
-
const p = config.persona;
|
|
230
|
+
function stateWarnings(ctx, config) {
|
|
231
231
|
return [
|
|
232
|
-
...checkCombos(config.axes
|
|
233
|
-
...(
|
|
232
|
+
...checkCombos(config.axes).map((w) => combination(w, ctx.t)),
|
|
233
|
+
...settingsWarnings(config, ctx.t, ctx.asJson),
|
|
234
234
|
...riskWarnings(config.axes, ctx.t),
|
|
235
|
-
...sizeWarning(size, ctx.t),
|
|
236
235
|
];
|
|
237
236
|
}
|
|
238
237
|
/**
|
package/dist/commands/init.js
CHANGED
|
@@ -13,7 +13,7 @@ import { BUNDLED, localizedPreset, matchesPreset, withPreset } from "../core/pre
|
|
|
13
13
|
import { SEED_VERSION, inspectContextLayout, planSeedChanges } from "../core/seeds.js";
|
|
14
14
|
import { inspectOperations } from "../core/operations.js";
|
|
15
15
|
import { SKILL_NAME, TONE_COMMAND_MD, TONE_COMMAND_VERSION } from "../core/skill.js";
|
|
16
|
-
import {
|
|
16
|
+
import { artifactSize, humanText, nativeSetup, receiptLines, recoveryRollbackLines, riskWarnings, section } from "../ui/format.js";
|
|
17
17
|
import { riskyAxes } from "../core/anchors.js";
|
|
18
18
|
import { padEnd, wrap } from "../ui/width.js";
|
|
19
19
|
import { gate, planChange } from "../wiring/apply.js";
|
|
@@ -204,7 +204,7 @@ export async function runInit(entry, _args) {
|
|
|
204
204
|
addReceipt(ctx.t.artifact.generated, ctx.ui.success);
|
|
205
205
|
}
|
|
206
206
|
if (ctx.flags.verbose) {
|
|
207
|
-
lines.push(` ${ctx.ui.dim(
|
|
207
|
+
lines.push(` ${ctx.ui.dim(artifactSize(size, ctx.t))}`);
|
|
208
208
|
// The seed list grows with every bundled preset, so it folds like any other sentence.
|
|
209
209
|
addReceipt(ctx.t.wiring.seeded(seeds.labels));
|
|
210
210
|
if (skills.length) {
|
|
@@ -219,11 +219,10 @@ export async function runInit(entry, _args) {
|
|
|
219
219
|
addReceipt(message);
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
addReceipt(notice, ctx.ui.risk);
|
|
222
|
+
if (applied) {
|
|
223
|
+
for (const notice of riskWarnings(config.axes, ctx.t))
|
|
224
|
+
addReceipt(notice, ctx.ui.risk);
|
|
225
|
+
}
|
|
227
226
|
lines.push("");
|
|
228
227
|
// Skills and controls invoke bare tonedial, so command reachability needs its own hint.
|
|
229
228
|
if (onPath("tonedial", ctx.env) === null) {
|
|
@@ -298,10 +297,6 @@ async function rebuildExisting(entry) {
|
|
|
298
297
|
const resultHeading = ctx.canPrompt && !ctx.flags.auto && !ctx.flags.dryRun
|
|
299
298
|
? section(copy.init.resultHeading, ctx.ui) : [];
|
|
300
299
|
const app = await runAppRebuild(ctx);
|
|
301
|
-
const riskIntro = [
|
|
302
|
-
...receiptLines(copy.init.risk, ctx.ui.width - 2).map(line => ` ${ctx.ui.warn(line)}`),
|
|
303
|
-
...receiptLines(ctx.t.notice.modelExpectation, ctx.ui.width - 2).map(line => ` ${line}`),
|
|
304
|
-
];
|
|
305
300
|
if (ctx.flags.dryRun) {
|
|
306
301
|
const answers = await ask(ctx, copy, false, selection);
|
|
307
302
|
const tools = selection ?? answers.tools;
|
|
@@ -309,7 +304,7 @@ async function rebuildExisting(entry) {
|
|
|
309
304
|
throw new ConfigError(ctx.t.errors.commandsNeedClaude);
|
|
310
305
|
const native = await runRebuildNative({ ...ctx, flags: { ...ctx.flags, tools: tools.length ? tools.join(",") : "none" } }, app.legacy, app.proposedConfig);
|
|
311
306
|
return {
|
|
312
|
-
lines: [...(ctx.canPrompt ? [] : introduction), ...app.lines, ...native.lines
|
|
307
|
+
lines: [...(ctx.canPrompt ? [] : introduction), ...app.lines, ...native.lines],
|
|
313
308
|
json: { ...app.json, agentRoot: ctx.agent.root, live: ctx.agent.live,
|
|
314
309
|
scope: ctx.agent.live ? "global" : "project", scopeExplicit, language: app.proposedConfig.language,
|
|
315
310
|
seedVersion: SEED_VERSION, tools, native: native.json,
|
|
@@ -320,7 +315,7 @@ async function rebuildExisting(entry) {
|
|
|
320
315
|
};
|
|
321
316
|
}
|
|
322
317
|
if (app.rebuiltConfig === null)
|
|
323
|
-
return { ...app, lines: [...(ctx.canPrompt ? [] : introduction), ...resultHeading, ...app.lines
|
|
318
|
+
return { ...app, lines: [...(ctx.canPrompt ? [] : introduction), ...resultHeading, ...app.lines] };
|
|
324
319
|
const answers = await ask(ctx, copy, false, selection);
|
|
325
320
|
const tools = selection ?? answers.tools;
|
|
326
321
|
if (ctx.flags.commands && !tools.includes("claude"))
|
|
@@ -331,7 +326,6 @@ async function rebuildExisting(entry) {
|
|
|
331
326
|
const after = codexHandoff(scoped, native.json.applied === true || native.json.reason === "nothing", codexConfigured);
|
|
332
327
|
return {
|
|
333
328
|
lines: [...(ctx.canPrompt ? [] : introduction), ...resultHeading, ...app.lines, ...native.lines,
|
|
334
|
-
...riskIntro,
|
|
335
329
|
...recoveryRollbackLines(ctx.t, app.json.operationId, native.json.operationId)],
|
|
336
330
|
...(after ? { after } : {}),
|
|
337
331
|
json: {
|
package/dist/commands/save.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { AXIS_DEFAULT, AXIS_ORDER } from "../core/anchors.js";
|
|
3
3
|
import { ConfigError, serializeConfig } from "../core/config.js";
|
|
4
4
|
import { BUNDLED, PRESET_SCHEMA, SLUG_PATTERN, preparePresetWrite, presetSettings, resolvePreset, slugify } from "../core/presets.js";
|
|
5
|
-
import {
|
|
5
|
+
import { artifactSize, humanText, nextStep } from "../ui/format.js";
|
|
6
6
|
import { cells, truncate, wrap } from "../ui/width.js";
|
|
7
7
|
import { PERSONA_DESCRIPTION_MAX } from "../core/combos.js";
|
|
8
|
-
import { applyPlanned, planArtifact, planConfig
|
|
8
|
+
import { applyPlanned, planArtifact, planConfig } from "./compile.js";
|
|
9
9
|
import { planChange, rawReadChange, rawReadCheck } from "../wiring/apply.js";
|
|
10
10
|
/** Only the axes that moved. Every axis is still emitted; sparsity is storage, not compilation. */
|
|
11
11
|
function movedValues(axes) {
|
|
@@ -73,27 +73,19 @@ export async function savePreset(ctx, displayName, state, options = {}) {
|
|
|
73
73
|
};
|
|
74
74
|
const count = Object.keys(values).length;
|
|
75
75
|
const countLabel = ctx.t.preset.nonDefault(count);
|
|
76
|
-
const warnings = [...sizeWarning(size, ctx.t)];
|
|
77
|
-
if (replaced)
|
|
78
|
-
warnings.push(ctx.t.preset.replaced(slug));
|
|
79
|
-
// Sparsity survives on one reason after the omit-defaults rule fell: fewer extremes mean
|
|
80
|
-
// fewer internal collisions. It is guidance, so it warns and never blocks.
|
|
81
|
-
if (count < 3 || count > 7) {
|
|
82
|
-
warnings.push(ctx.t.preset.sparsity(slug, count));
|
|
83
|
-
}
|
|
84
76
|
return {
|
|
85
77
|
// Truncated, not folded. A display name has no length cap, and folding one across two lines
|
|
86
78
|
// makes the slug beside it harder to read than losing the tail does.
|
|
87
79
|
lines: [
|
|
88
80
|
...(options.create ? result.lines : []),
|
|
89
|
-
|
|
81
|
+
...wrap(replaced ? ctx.t.preset.replaced(slug) : ctx.t.preset.savedTarget(slug), ctx.ui.width - 2)
|
|
82
|
+
.map((line) => ` ${ctx.ui.success(ctx.ui.bold(line))}`),
|
|
90
83
|
` ${truncate(humanText(displayName), Math.max(1, ctx.ui.width - cells(` ${countLabel}`)))} ${ctx.ui.dim(countLabel)}`,
|
|
91
84
|
` ${ctx.t.artifact.generated}`,
|
|
92
|
-
...(ctx.flags.verbose ? [` ${ctx.ui.dim(
|
|
85
|
+
...(ctx.flags.verbose ? [` ${ctx.ui.dim(artifactSize(size, ctx.t))}`] : []),
|
|
93
86
|
...nextStep("tonedial list", ctx.ui),
|
|
94
87
|
],
|
|
95
88
|
json: { slug, displayName, values, settings: preset.settings, nonDefaultAxes: count, replaced, chars: size.chars,
|
|
96
89
|
...(options.create ? { created: true, diff: result.diff, operationId: result.operationId } : {}) },
|
|
97
|
-
warnings,
|
|
98
90
|
};
|
|
99
91
|
}
|