@ultimat3/cli 19.3.2 → 19.3.3
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/package.json +29 -29
- package/src/verify-checks.ts +9 -2
- package/src/verify-floor.ts +52 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultimat3/cli",
|
|
3
|
-
"version": "19.3.
|
|
3
|
+
"version": "19.3.3",
|
|
4
4
|
"description": "The `x` binary: new, dev, build, verify, generate, db, mcp, doctor, deploy",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,34 +37,34 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@babel/core": "^7.28.4",
|
|
40
|
-
"@ultimat3/action": "19.3.
|
|
41
|
-
"@ultimat3/admin": "19.3.
|
|
42
|
-
"@ultimat3/ai": "19.3.
|
|
43
|
-
"@ultimat3/auth": "19.3.
|
|
44
|
-
"@ultimat3/cache": "19.3.
|
|
45
|
-
"@ultimat3/core": "19.3.
|
|
46
|
-
"@ultimat3/db": "19.3.
|
|
47
|
-
"@ultimat3/entity": "19.3.
|
|
48
|
-
"@ultimat3/flags": "19.3.
|
|
49
|
-
"@ultimat3/http": "19.3.
|
|
50
|
-
"@ultimat3/i18n": "19.3.
|
|
51
|
-
"@ultimat3/jobs": "19.3.
|
|
52
|
-
"@ultimat3/mail": "19.3.
|
|
53
|
-
"@ultimat3/manifest": "19.3.
|
|
54
|
-
"@ultimat3/mcp": "19.3.
|
|
55
|
-
"@ultimat3/money": "19.3.
|
|
56
|
-
"@ultimat3/notify": "19.3.
|
|
57
|
-
"@ultimat3/policy": "19.3.
|
|
58
|
-
"@ultimat3/pwa": "19.3.
|
|
59
|
-
"@ultimat3/query": "19.3.
|
|
60
|
-
"@ultimat3/realtime": "19.3.
|
|
61
|
-
"@ultimat3/render": "19.3.
|
|
62
|
-
"@ultimat3/schema": "19.3.
|
|
63
|
-
"@ultimat3/scraping": "19.3.
|
|
64
|
-
"@ultimat3/seo": "19.3.
|
|
65
|
-
"@ultimat3/storage": "19.3.
|
|
66
|
-
"@ultimat3/testing": "19.3.
|
|
67
|
-
"@ultimat3/time": "19.3.
|
|
40
|
+
"@ultimat3/action": "19.3.3",
|
|
41
|
+
"@ultimat3/admin": "19.3.3",
|
|
42
|
+
"@ultimat3/ai": "19.3.3",
|
|
43
|
+
"@ultimat3/auth": "19.3.3",
|
|
44
|
+
"@ultimat3/cache": "19.3.3",
|
|
45
|
+
"@ultimat3/core": "19.3.3",
|
|
46
|
+
"@ultimat3/db": "19.3.3",
|
|
47
|
+
"@ultimat3/entity": "19.3.3",
|
|
48
|
+
"@ultimat3/flags": "19.3.3",
|
|
49
|
+
"@ultimat3/http": "19.3.3",
|
|
50
|
+
"@ultimat3/i18n": "19.3.3",
|
|
51
|
+
"@ultimat3/jobs": "19.3.3",
|
|
52
|
+
"@ultimat3/mail": "19.3.3",
|
|
53
|
+
"@ultimat3/manifest": "19.3.3",
|
|
54
|
+
"@ultimat3/mcp": "19.3.3",
|
|
55
|
+
"@ultimat3/money": "19.3.3",
|
|
56
|
+
"@ultimat3/notify": "19.3.3",
|
|
57
|
+
"@ultimat3/policy": "19.3.3",
|
|
58
|
+
"@ultimat3/pwa": "19.3.3",
|
|
59
|
+
"@ultimat3/query": "19.3.3",
|
|
60
|
+
"@ultimat3/realtime": "19.3.3",
|
|
61
|
+
"@ultimat3/render": "19.3.3",
|
|
62
|
+
"@ultimat3/schema": "19.3.3",
|
|
63
|
+
"@ultimat3/scraping": "19.3.3",
|
|
64
|
+
"@ultimat3/seo": "19.3.3",
|
|
65
|
+
"@ultimat3/storage": "19.3.3",
|
|
66
|
+
"@ultimat3/testing": "19.3.3",
|
|
67
|
+
"@ultimat3/time": "19.3.3",
|
|
68
68
|
"babel-preset-solid": "^1.9.15"
|
|
69
69
|
}
|
|
70
70
|
}
|
package/src/verify-checks.ts
CHANGED
|
@@ -50,14 +50,21 @@ export const VERIFY_STEPS: readonly VerifyStep[] = [
|
|
|
50
50
|
{
|
|
51
51
|
name: 'typecheck',
|
|
52
52
|
summary: 'tsc -b across every project the root references',
|
|
53
|
+
// `typecheckBin` (`x.verify.json`, beside `agentsMdMaxBytes`) swaps the binary and nothing
|
|
54
|
+
// else: same `-b --pretty false` invocation, same output format to parse, same `X_TYPECHECK_
|
|
55
|
+
// FAILED` finding either way. Absent means `tsc` — the only checker every app already has,
|
|
56
|
+
// since `typescript` is a framework dependency and a drop-in replacement is the app's own
|
|
57
|
+
// devDependency to add, never a default this step could assume.
|
|
53
58
|
async run(ctx) {
|
|
54
|
-
const
|
|
59
|
+
const floor = await readVerifyFloor(ctx.root);
|
|
60
|
+
const bin = floor?.typecheckBin ?? 'tsc';
|
|
61
|
+
const result = await ctx.runner(['bunx', bin, '-b', '--pretty', 'false'], {
|
|
55
62
|
cwd: ctx.root,
|
|
56
63
|
});
|
|
57
64
|
return fromExec(result, {
|
|
58
65
|
code: 'X_TYPECHECK_FAILED',
|
|
59
66
|
cause: 'the project does not typecheck',
|
|
60
|
-
fix:
|
|
67
|
+
fix: `bunx ${bin} -b --pretty false`,
|
|
61
68
|
});
|
|
62
69
|
},
|
|
63
70
|
},
|
package/src/verify-floor.ts
CHANGED
|
@@ -29,6 +29,18 @@ export interface VerifyFloor {
|
|
|
29
29
|
* sees, which is the whole safeguard: the number is small, visible, and argued for in one place.
|
|
30
30
|
*/
|
|
31
31
|
readonly agentsMdMaxBytes?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The binary the `typecheck` step invokes in place of `tsc` — `bunx <typecheckBin> -b --pretty
|
|
34
|
+
* false`, unchanged otherwise. Absent means `tsc`, which is the only binary every app already
|
|
35
|
+
* has: `typescript` is a framework dependency, not one this file can assume an app added.
|
|
36
|
+
*
|
|
37
|
+
* Here for the same reason `agentsMdMaxBytes` is: this is the file that configures the GATE,
|
|
38
|
+
* and it is read by the very step the key names. A drop-in `tsc -b` compatible checker (Microsoft's
|
|
39
|
+
* `tsgo`, `@typescript/native-preview`) is a devDependency + a one-line commit here, never a
|
|
40
|
+
* hardcoded default — an app that has not installed the binary this names gets `command not
|
|
41
|
+
* found` from its own shell, not a framework opinion about which compiler is correct.
|
|
42
|
+
*/
|
|
43
|
+
readonly typecheckBin?: string;
|
|
32
44
|
/** Why part of the file is not a floor. The `manifest` step reports these; nothing swallows them. */
|
|
33
45
|
readonly problems: readonly string[];
|
|
34
46
|
}
|
|
@@ -36,6 +48,9 @@ export interface VerifyFloor {
|
|
|
36
48
|
/** The floor's budget key. Named once: the problem quotes it and the fix repairs it. */
|
|
37
49
|
export const BUDGET_FIELD = 'agentsMdMaxBytes';
|
|
38
50
|
|
|
51
|
+
/** The floor's typecheck-binary key. Named once: the problem quotes it and the fix repairs it. */
|
|
52
|
+
export const TYPECHECK_BIN_FIELD = 'typecheckBin';
|
|
53
|
+
|
|
39
54
|
/**
|
|
40
55
|
* `agentsMdMaxBytes`, or a reason it is not one. A budget that is not a positive whole number is
|
|
41
56
|
* the caller's bug and must not silently fall back to the default: a floor file that says
|
|
@@ -57,6 +72,27 @@ function readBudget(payload: Record<string, unknown> | undefined): {
|
|
|
57
72
|
return { budget: raw, problems: [] };
|
|
58
73
|
}
|
|
59
74
|
|
|
75
|
+
/**
|
|
76
|
+
* `typecheckBin`, or a reason it is not one. A non-string value must not silently fall back to
|
|
77
|
+
* `tsc`: a floor that names `"typecheckBin": 7` and gets `tsc` anyway is a repository that
|
|
78
|
+
* believes the `typecheck` step is running a checker it is not, which is the same false green
|
|
79
|
+
* `readBudget` above already refuses for the byte count. An empty string is refused for the same
|
|
80
|
+
* reason `-b`'s own project argument may not be empty — `bunx '' -b …` is not a step that failed
|
|
81
|
+
* to typecheck, it is a step that never ran a compiler at all.
|
|
82
|
+
*/
|
|
83
|
+
function readTypecheckBin(payload: Record<string, unknown> | undefined): {
|
|
84
|
+
bin?: string;
|
|
85
|
+
problems: readonly string[];
|
|
86
|
+
} {
|
|
87
|
+
const raw = payload?.[TYPECHECK_BIN_FIELD];
|
|
88
|
+
if (raw === undefined) return { problems: [] };
|
|
89
|
+
if (typeof raw !== 'string' || raw.trim().length === 0)
|
|
90
|
+
return {
|
|
91
|
+
problems: [`"${TYPECHECK_BIN_FIELD}" is ${JSON.stringify(raw)}, which is not a binary name`],
|
|
92
|
+
};
|
|
93
|
+
return { bin: raw, problems: [] };
|
|
94
|
+
}
|
|
95
|
+
|
|
60
96
|
const asRecord = (value: unknown): Record<string, unknown> | undefined =>
|
|
61
97
|
typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
62
98
|
? (value as Record<string, unknown>)
|
|
@@ -86,12 +122,18 @@ export function parseVerifyFloor(
|
|
|
86
122
|
}
|
|
87
123
|
const record = asRecord(payload);
|
|
88
124
|
const budget = readBudget(record);
|
|
125
|
+
const typecheckBin = readTypecheckBin(record);
|
|
89
126
|
const steps = record?.['steps'];
|
|
90
127
|
if (!Array.isArray(steps)) {
|
|
91
128
|
return {
|
|
92
129
|
steps: [],
|
|
93
130
|
...(budget.budget === undefined ? {} : { agentsMdMaxBytes: budget.budget }),
|
|
94
|
-
|
|
131
|
+
...(typecheckBin.bin === undefined ? {} : { typecheckBin: typecheckBin.bin }),
|
|
132
|
+
problems: [
|
|
133
|
+
'it has no "steps" array of step names',
|
|
134
|
+
...budget.problems,
|
|
135
|
+
...typecheckBin.problems,
|
|
136
|
+
],
|
|
95
137
|
};
|
|
96
138
|
}
|
|
97
139
|
const named = steps.filter((step): step is string => typeof step === 'string');
|
|
@@ -99,8 +141,10 @@ export function parseVerifyFloor(
|
|
|
99
141
|
return {
|
|
100
142
|
steps: named.filter((step) => declared.includes(step)),
|
|
101
143
|
...(budget.budget === undefined ? {} : { agentsMdMaxBytes: budget.budget }),
|
|
144
|
+
...(typecheckBin.bin === undefined ? {} : { typecheckBin: typecheckBin.bin }),
|
|
102
145
|
problems: [
|
|
103
146
|
...(named.length === steps.length ? [] : ['"steps" holds an entry that is not a string']),
|
|
147
|
+
...typecheckBin.problems,
|
|
104
148
|
...(unknown.length === 0
|
|
105
149
|
? []
|
|
106
150
|
: [`"steps" names ${unknown.join(', ')}, which x verify does not run`]),
|
|
@@ -185,7 +229,10 @@ export const floorProblemFindings = (floor: VerifyFloor | undefined): readonly F
|
|
|
185
229
|
* does not fix it is the failure `packages/cli/CLAUDE.md` names, and the budget is the first
|
|
186
230
|
* problem this file can report that is not about `steps` at all.
|
|
187
231
|
*/
|
|
188
|
-
const fixFor = (problem: string): string =>
|
|
189
|
-
problem.includes(`"${BUDGET_FIELD}"`)
|
|
190
|
-
|
|
191
|
-
|
|
232
|
+
const fixFor = (problem: string): string => {
|
|
233
|
+
if (problem.includes(`"${BUDGET_FIELD}"`))
|
|
234
|
+
return `x verify --json # then set "${BUDGET_FIELD}" in ${VERIFY_FLOOR_FILE} to a positive whole number of bytes, or drop the key for the ${AGENTS_MD_MAX_BYTES}B default`;
|
|
235
|
+
if (problem.includes(`"${TYPECHECK_BIN_FIELD}"`))
|
|
236
|
+
return `x verify --json # then set "${TYPECHECK_BIN_FIELD}" in ${VERIFY_FLOOR_FILE} to a non-empty binary name, or drop the key to run tsc`;
|
|
237
|
+
return `x verify --json # then write ${VERIFY_FLOOR_FILE} as {"steps":["unit","contract"]}, naming only steps it ran`;
|
|
238
|
+
};
|