synthesisui 0.16.60 → 0.16.62
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/commands/import.js +23 -8
- package/dist/index.js +4 -1
- package/dist/skill-import.js +80 -16
- package/package.json +1 -1
package/dist/commands/import.js
CHANGED
|
@@ -637,11 +637,11 @@ async function sayIfWorkspace(root) {
|
|
|
637
637
|
console.log("");
|
|
638
638
|
if (shared.length > 0) {
|
|
639
639
|
console.log(body("The shape that works, if your vocabulary is shared:"));
|
|
640
|
-
console.log(body(` ${paint.strong(`synthesisui import --
|
|
640
|
+
console.log(body(` ${paint.strong(`synthesisui import --scope ${shared[0]}`)} ${paint.faint("the system comes from here")}`));
|
|
641
641
|
}
|
|
642
642
|
else {
|
|
643
643
|
console.log(body("The shape that works:"));
|
|
644
|
-
console.log(body(` ${paint.strong(`synthesisui import --
|
|
644
|
+
console.log(body(` ${paint.strong(`synthesisui import --scope ${apps[0]}`)} ${paint.faint("one app, one vocabulary")}`));
|
|
645
645
|
}
|
|
646
646
|
for (const app of apps.slice(0, 3)) {
|
|
647
647
|
console.log(body(` ${paint.dim(`synthesisui doctor ${app}`)} ${paint.faint("how far this one is from it")}`));
|
|
@@ -863,6 +863,16 @@ function sayReach(c) {
|
|
|
863
863
|
}
|
|
864
864
|
export async function runImport(opts) {
|
|
865
865
|
const root = opts.root ?? process.cwd();
|
|
866
|
+
/**
|
|
867
|
+
* WHAT TO READ, as opposed to WHERE TO WRITE. In a monorepo the design
|
|
868
|
+
* decisions live in one package and the governance belongs at the root, and
|
|
869
|
+
* conflating the two meant every re-measure scattered another census.
|
|
870
|
+
*/
|
|
871
|
+
const scope = opts.scope
|
|
872
|
+
?.trim()
|
|
873
|
+
.replace(/^\.\/+/, "")
|
|
874
|
+
.replace(/\/+$/, "");
|
|
875
|
+
const readFrom = scope ? join(root, scope) : root;
|
|
866
876
|
// A census handed to us (an agent annotated it) is sent as-is; the numbers
|
|
867
877
|
// inside were still ours to begin with.
|
|
868
878
|
let census;
|
|
@@ -889,15 +899,20 @@ export async function runImport(opts) {
|
|
|
889
899
|
}
|
|
890
900
|
else {
|
|
891
901
|
console.log(section("Reading your project"));
|
|
892
|
-
census = await takeCensus(
|
|
902
|
+
census = await takeCensus(readFrom);
|
|
903
|
+
if (scope)
|
|
904
|
+
census.scope = scope;
|
|
893
905
|
}
|
|
894
906
|
summarize(census);
|
|
895
|
-
|
|
907
|
+
// Only when nobody has scoped yet. Telling someone to scope to the folder
|
|
908
|
+
// they just scoped to reads as the tool not having noticed.
|
|
909
|
+
if (!opts.census && !scope)
|
|
896
910
|
await sayIfWorkspace(root);
|
|
897
|
-
// A census handed to us is written BACK TO ITSELF
|
|
898
|
-
//
|
|
899
|
-
//
|
|
900
|
-
//
|
|
911
|
+
// A census handed to us is written BACK TO ITSELF; one we took lands at the
|
|
912
|
+
// ROOT, whatever it measured. Everything else in `_synthesisui/` is anchored
|
|
913
|
+
// there - config, `ds/<slug>/`, the hook's marker - and the census was the
|
|
914
|
+
// only artefact that travelled with `--dir`, which is how two of them ended
|
|
915
|
+
// up disagreeing about which import happened (dono, 31/07).
|
|
901
916
|
const out = opts.census ?? join(root, "_synthesisui", "census.json");
|
|
902
917
|
await mkdir(dirname(out), { recursive: true });
|
|
903
918
|
await writeFile(out, `${JSON.stringify(census, null, 2)}\n`, "utf8");
|
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ Usage - deterministic, FREE:
|
|
|
41
41
|
|
|
42
42
|
Usage - governance (deterministic, FREE):
|
|
43
43
|
synthesisui adopt [--write] turn the design system you ALREADY have into a contract
|
|
44
|
-
synthesisui import [--dry] [--
|
|
44
|
+
synthesisui import [--dry] [--scope <p>] read the app you already have and make it a system
|
|
45
45
|
your agent follows - without touching your CSS
|
|
46
46
|
synthesisui connect wire your agent: the check as an editor hook, the system
|
|
47
47
|
as MCP tools, and a contract that stops repeating itself
|
|
@@ -66,6 +66,7 @@ Options:
|
|
|
66
66
|
--version <n> install a specific version (default: latest)
|
|
67
67
|
--ds <slug> init: bring this DS in right away · generate: target DS (default: installed)
|
|
68
68
|
--name <name> preferred component name for generate
|
|
69
|
+
--scope <path> import: measure only this folder; the census still lands at the root
|
|
69
70
|
--scheme <s> dark|light - which end of your ladder is the default
|
|
70
71
|
--target <t> template/init target: next | general (default: next)
|
|
71
72
|
--pages-dir <dir> init: folder for generated pages (default: app)
|
|
@@ -162,6 +163,8 @@ async function main() {
|
|
|
162
163
|
name: typeof flags.name === "string" ? flags.name : undefined,
|
|
163
164
|
// Only these two words. Anything else is a typo that would silently
|
|
164
165
|
// invert a system, so it falls through to being measured and asked.
|
|
166
|
+
// WHAT to read. `--dir` stays WHERE the project is, in every command.
|
|
167
|
+
scope: typeof flags.scope === "string" ? flags.scope : undefined,
|
|
165
168
|
scheme: flags.scheme === "dark" || flags.scheme === "light"
|
|
166
169
|
? flags.scheme
|
|
167
170
|
: undefined,
|
package/dist/skill-import.js
CHANGED
|
@@ -67,19 +67,61 @@ So if the file says \`"registry": "http://localhost:3000"\`, every command in th
|
|
|
67
67
|
\`--registry http://localhost:3000\`. If it says production, pass nothing. The CLI now refuses a
|
|
68
68
|
mismatch instead of letting the server reject it, but the point is not to reach that.
|
|
69
69
|
|
|
70
|
+
**Do this silently.** Which host you are pointed at and which flags follow from it is plumbing,
|
|
71
|
+
and narrating it - *"registry is production, so no --registry flag needed"* - spends the
|
|
72
|
+
person's attention on a decision that was never theirs (dono, 01/08). Say something only when
|
|
73
|
+
there is nothing to say to: no token, or the wrong host.
|
|
74
|
+
|
|
75
|
+
## How to narrate
|
|
76
|
+
|
|
77
|
+
The person cares about **what you found in their code** and **what you are about to create**.
|
|
78
|
+
They do not care which flag you passed, which grep you ran, or what you checked and ruled out.
|
|
79
|
+
|
|
80
|
+
- Report findings, not mechanics. *"Their docs call Ocean the primary branding scale"* earns
|
|
81
|
+
its line. *"Let me check whether packages/ui exists"* does not.
|
|
82
|
+
- Every decision you make on their behalf belongs in **one** confirmation at the end, not
|
|
83
|
+
scattered through the work as fait accompli.
|
|
84
|
+
- Never end on a wall of prose that happens to contain a question. If you need an answer, the
|
|
85
|
+
last thing on screen is the question.
|
|
86
|
+
|
|
70
87
|
### 1. Measure
|
|
71
88
|
|
|
89
|
+
**Always run from the project root, and always twice in a monorepo.** The root is where the
|
|
90
|
+
governance lives - \`_synthesisui/config.json\`, \`ds/<slug>/\`, and the census. One root, one
|
|
91
|
+
census; re-measuring overwrites it rather than leaving copies to send the wrong one.
|
|
92
|
+
|
|
93
|
+
First, unscoped, to find out what kind of repo this is:
|
|
94
|
+
|
|
72
95
|
\`\`\`
|
|
73
|
-
npx synthesisui import --dry
|
|
96
|
+
npx synthesisui import --dry
|
|
74
97
|
\`\`\`
|
|
75
98
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
candidates and ranks them by how many tokens they declare; if it printed a workspace summary,
|
|
79
|
-
read it before choosing. Scoping to the wrong folder measures the wrong thing, and the score
|
|
80
|
-
it reports will be meaninglessly low.
|
|
99
|
+
If it is a single app, that census is the one. If it holds several projects, the CLI says so
|
|
100
|
+
and **names the candidates itself**, ranked by how many tokens each declares:
|
|
81
101
|
|
|
82
|
-
|
|
102
|
+
\`\`\`
|
|
103
|
+
This root holds several projects
|
|
104
|
+
3 apps (apps/web-admin, apps/web-dashboard, apps/web-review) - and this census
|
|
105
|
+
is the average of all of them. That is a fine DIAGNOSIS and a poor system: a
|
|
106
|
+
light app and a dark one average into a palette that is neither.
|
|
107
|
+
|
|
108
|
+
synthesisui import --scope packages/ui the system comes from here
|
|
109
|
+
\`\`\`
|
|
110
|
+
|
|
111
|
+
Then measure again, narrowed:
|
|
112
|
+
|
|
113
|
+
\`\`\`
|
|
114
|
+
npx synthesisui import --dry --scope packages/ui
|
|
115
|
+
\`\`\`
|
|
116
|
+
|
|
117
|
+
**Do not import the average.** Three apps measured together produce a palette that belongs to
|
|
118
|
+
none of them, and it will look plausible - a real monorepo reported 36% coverage across 2797
|
|
119
|
+
files at the root and 47% across 114 in its shared package. The second number is the system;
|
|
120
|
+
the first is a diagnosis.
|
|
121
|
+
|
|
122
|
+
\`--scope\` narrows what is READ. The census still lands at \`<root>/_synthesisui/census.json\`
|
|
123
|
+
and records what it measured, so you always send the same path and there is never a second
|
|
124
|
+
file to pick between. Nothing is sent by \`--dry\`. Read the file.
|
|
83
125
|
|
|
84
126
|
### 2. Read what arithmetic cannot
|
|
85
127
|
|
|
@@ -124,21 +166,43 @@ about which one is the page. Read a screen and see.
|
|
|
124
166
|
**\`fonts\` and \`concept\`** - the voice, and one paragraph on what this product is. The concept
|
|
125
167
|
feeds every recommendation downstream, so a real one beats a generic one by a wide margin.
|
|
126
168
|
|
|
127
|
-
### 3.
|
|
169
|
+
### 3. Confirm once, then send
|
|
170
|
+
|
|
171
|
+
You have made three decisions on their behalf by now - **where** you measured, **what** it will
|
|
172
|
+
be called, and **which values** carry which meaning. Put all three in one place and ask. Not a
|
|
173
|
+
report that contains a question at the bottom: a question.
|
|
174
|
+
|
|
175
|
+
Offer the alternatives you actually considered, so choosing is a choice and not a veto:
|
|
176
|
+
|
|
177
|
+
\`\`\`
|
|
178
|
+
I'd create a system from packages/ui, called SignalUI, opening dark.
|
|
179
|
+
|
|
180
|
+
from packages/ui 114 files, 47% of its values already named
|
|
181
|
+
(apps/web-dashboard, apps/web-review and apps/web-admin
|
|
182
|
+
are the consumers; measuring all of them gave 36%, which
|
|
183
|
+
is the average of a light app and two dark ones)
|
|
184
|
+
called SignalUI their own name, from Introduction.mdx
|
|
185
|
+
brand #059aed their docs call Ocean the primary scale
|
|
186
|
+
opens dark data-theme="dark" in the root layout
|
|
187
|
+
|
|
188
|
+
This creates it on your account. Go ahead, or change any of these?
|
|
189
|
+
\`\`\`
|
|
190
|
+
|
|
191
|
+
Then, and only after they answer:
|
|
128
192
|
|
|
129
193
|
\`\`\`
|
|
130
|
-
npx synthesisui import --census _synthesisui/census.json --name "<
|
|
194
|
+
npx synthesisui import --census _synthesisui/census.json --name "<the name>" [--registry <from step 0>]
|
|
131
195
|
\`\`\`
|
|
132
196
|
|
|
133
|
-
**
|
|
134
|
-
and what it will be called before you run it.
|
|
197
|
+
**This is the one real write.** Everything before it is on their disk and costs nothing to redo.
|
|
135
198
|
|
|
136
|
-
The CLI asks for a name unless \`--name\` is passed
|
|
137
|
-
your reading already answered - a second question would only be a chance to contradict you.
|
|
199
|
+
The CLI asks for a name unless \`--name\` is passed, and it does **not** ask about the scheme when
|
|
200
|
+
your reading already answered - a second question would only be a chance to contradict you. So
|
|
201
|
+
if you skip the confirmation above, nobody is asked about the scope at all, and the first time
|
|
202
|
+
they learn where their system came from is when they open it.
|
|
138
203
|
|
|
139
|
-
If it refuses, it
|
|
140
|
-
|
|
141
|
-
from the census already on disk; none of them need a re-measure.
|
|
204
|
+
If it refuses, it says which of the three it is: no session, an expired one, or a token issued
|
|
205
|
+
by a different host. All are recoverable from the census on disk; none need a re-measure.
|
|
142
206
|
|
|
143
207
|
### 4. Tell them exactly what they have, and what is theirs to decide
|
|
144
208
|
|
package/package.json
CHANGED