aontu 0.63.0 → 0.65.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/README.md +8 -8
- package/dist/agentsmd.js +3 -3
- package/dist/agentsmd.js.map +1 -1
- package/dist/aontu.d.ts +3 -3
- package/dist/aontu.js +4 -6
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.js +6 -12
- package/dist/aontumodel.js.map +1 -1
- package/dist/casing.d.ts +5 -0
- package/dist/casing.js +90 -0
- package/dist/casing.js.map +1 -0
- package/dist/cli.d.ts +16 -3
- package/dist/cli.js +653 -455
- package/dist/cli.js.map +1 -1
- package/dist/compat.d.ts +7 -0
- package/dist/compat.js +113 -0
- package/dist/compat.js.map +1 -0
- package/dist/helpdoc.js +5 -5
- package/dist/helpdoc.js.map +1 -1
- package/dist/hints.js +14 -5
- package/dist/hints.js.map +1 -1
- package/dist/lang.d.ts +1 -0
- package/dist/lang.js +8 -0
- package/dist/lang.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/mcp.js +0 -36
- package/dist/mcp.js.map +1 -1
- package/dist/mod.d.ts +18 -3
- package/dist/mod.js +117 -46
- package/dist/mod.js.map +1 -1
- package/dist/pkg-net.d.ts +227 -0
- package/dist/pkg-net.js +1598 -0
- package/dist/pkg-net.js.map +1 -0
- package/dist/pkg-zip.d.ts +8 -0
- package/dist/pkg-zip.js +196 -0
- package/dist/pkg-zip.js.map +1 -0
- package/dist/pkg.d.ts +159 -0
- package/dist/pkg.js +767 -0
- package/dist/pkg.js.map +1 -0
- package/dist/profile.d.ts +9 -0
- package/dist/profile.js +28 -0
- package/dist/profile.js.map +1 -0
- package/dist/report-sarif.js +1 -1
- package/dist/report-sarif.js.map +1 -1
- package/dist/subsume.d.ts +3 -1
- package/dist/subsume.js +2 -0
- package/dist/subsume.js.map +1 -1
- package/dist/trace.d.ts +21 -0
- package/dist/trace.js +107 -0
- package/dist/trace.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/unify.js +1 -6
- package/dist/unify.js.map +1 -1
- package/dist/val/CmpFuncVal.d.ts +2 -0
- package/dist/val/CmpFuncVal.js +47 -13
- package/dist/val/CmpFuncVal.js.map +1 -1
- package/dist/val/NomFuncVal.js +11 -13
- package/dist/val/NomFuncVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +3 -0
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +3 -3
- package/skill/error-codes.md +4 -4
- package/skill/examples.md +4 -4
- package/skill/grammar-card.md +1 -1
- package/skill/init/check.sh +2 -2
- package/skill/tasks.md +14 -12
- package/src/agentsmd.ts +3 -3
- package/src/aontu.ts +3 -8
- package/src/aontumodel.ts +6 -12
- package/src/casing.ts +95 -0
- package/src/cli.ts +758 -495
- package/src/compat.ts +148 -0
- package/src/helpdoc.ts +5 -5
- package/src/hints.ts +14 -7
- package/src/lang.ts +9 -1
- package/src/mcp.ts +0 -39
- package/src/mod.ts +142 -51
- package/src/pkg-net.ts +1945 -0
- package/src/pkg-zip.ts +228 -0
- package/src/pkg.ts +1018 -0
- package/src/profile.ts +42 -0
- package/src/report-sarif.ts +1 -1
- package/src/subsume.ts +2 -2
- package/src/trace.ts +157 -0
- package/src/unify.ts +1 -6
- package/src/val/CmpFuncVal.ts +66 -20
- package/src/val/NomFuncVal.ts +3 -5
- package/src/val/ReferFuncVal.ts +4 -0
- package/dist/lower.d.ts +0 -23
- package/dist/lower.js +0 -528
- package/dist/lower.js.map +0 -1
- package/dist/mod-tool.d.ts +0 -58
- package/dist/mod-tool.js +0 -403
- package/dist/mod-tool.js.map +0 -1
- package/dist/render.d.ts +0 -53
- package/dist/render.js +0 -432
- package/dist/render.js.map +0 -1
- package/src/lower.ts +0 -586
- package/src/mod-tool.ts +0 -561
- package/src/render.ts +0 -580
package/src/mod.ts
CHANGED
|
@@ -5,9 +5,9 @@ import { join as pathJoin, dirname as pathDirname } from 'node:path'
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
export type ModuleRef = {
|
|
8
|
-
// The
|
|
8
|
+
// The package path, or the alias key `alias:<name>` when the import
|
|
9
|
+
// spells one; an alias is resolved by lookup, never by shape.
|
|
9
10
|
path: string
|
|
10
|
-
major: number
|
|
11
11
|
// The inline canon-hash pin, if the import froze one.
|
|
12
12
|
hash?: string
|
|
13
13
|
}
|
|
@@ -19,23 +19,32 @@ export type ModuleFs = {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
// A package path is `<domain>/<path>` and carries no major (ADR-022).
|
|
22
23
|
const MODULE_RE =
|
|
23
|
-
/^([a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+(?:\/[A-Za-z0-9._-]+)*)
|
|
24
|
+
/^([a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+(?:\/[A-Za-z0-9._-]+)*)(?:#(aon1-[A-Za-z0-9_-]+))?$/
|
|
25
|
+
|
|
26
|
+
const ALIAS_RE = /^(alias:[A-Za-z0-9._-]+)(?:#(aon1-[A-Za-z0-9_-]+))?$/
|
|
27
|
+
|
|
28
|
+
export const ALIAS_PREFIX = 'alias:'
|
|
24
29
|
|
|
25
30
|
|
|
26
31
|
export function parseModuleRef(spec: string): ModuleRef | undefined {
|
|
27
|
-
const m = MODULE_RE.exec(spec)
|
|
32
|
+
const m = MODULE_RE.exec(spec) ?? ALIAS_RE.exec(spec)
|
|
28
33
|
if (null == m) {
|
|
29
34
|
return undefined
|
|
30
35
|
}
|
|
31
36
|
return {
|
|
32
37
|
path: m[1],
|
|
33
|
-
|
|
34
|
-
...(null == m[3] ? {} : { hash: m[3] }),
|
|
38
|
+
...(null == m[2] ? {} : { hash: m[2] }),
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
|
|
43
|
+
export function isAlias(path: string): boolean {
|
|
44
|
+
return path.startsWith(ALIAS_PREFIX)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
39
48
|
export const MODULE_MAX_PATH = 512
|
|
40
49
|
export const MODULE_MAX_ELEMS = 32
|
|
41
50
|
|
|
@@ -73,21 +82,42 @@ export function validateModulePath(path: string): string | undefined {
|
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
|
|
76
|
-
|
|
85
|
+
// The final element of a routed path, when it carries an extension the
|
|
86
|
+
// include table knows, was meant as a file: the commonest mistake once
|
|
87
|
+
// the major left the name (ADR-022 part 4), so it gets its own message.
|
|
88
|
+
export function localFileExt(path: string): string | undefined {
|
|
89
|
+
const last = path.split('/').pop() as string
|
|
90
|
+
const m = /\.([^.]+)$/.exec(last)
|
|
91
|
+
return null == m ? undefined : m[1].toLowerCase()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
export function escapeElem(elem: string): string {
|
|
77
96
|
return elem.replace(/[A-Z]/g, (c) => '!' + c.toLowerCase())
|
|
78
97
|
}
|
|
79
98
|
|
|
80
99
|
|
|
81
|
-
|
|
82
|
-
|
|
100
|
+
// The directory a key lives at under a store: one directory per
|
|
101
|
+
// element, uppercase escaped; an alias under `alias/<name>`, which no
|
|
102
|
+
// package path can spell because a domain carries a dot.
|
|
103
|
+
export function moduleDir(store: string, path: string): string {
|
|
104
|
+
const elems = isAlias(path) ?
|
|
105
|
+
['alias', path.slice(ALIAS_PREFIX.length)] : path.split('/')
|
|
106
|
+
return pathJoin(store, ...elems.map(escapeElem))
|
|
83
107
|
}
|
|
84
108
|
|
|
85
109
|
|
|
110
|
+
export const PKG_FILE = 'pkg.aon'
|
|
111
|
+
export const LOCK_FILE = 'pkg-lock.aon'
|
|
112
|
+
export const META_DIR = 'aontu_meta'
|
|
113
|
+
export const VENDOR_DIR = 'vendor'
|
|
114
|
+
|
|
115
|
+
|
|
86
116
|
export function projectRoots(from: string, fs: ModuleFs): string[] {
|
|
87
117
|
const roots: string[] = []
|
|
88
118
|
let dir = from
|
|
89
119
|
for (; ;) {
|
|
90
|
-
if (fs.existsSync(pathJoin(dir,
|
|
120
|
+
if (fs.existsSync(pathJoin(dir, PKG_FILE))) {
|
|
91
121
|
roots.push(dir)
|
|
92
122
|
}
|
|
93
123
|
const up = pathDirname(dir)
|
|
@@ -118,25 +148,42 @@ export function modCacheDirFor(
|
|
|
118
148
|
): string | undefined {
|
|
119
149
|
const xdg = env.XDG_CACHE_HOME
|
|
120
150
|
if ('string' === typeof xdg && '' !== xdg) {
|
|
121
|
-
return pathJoin(xdg, 'aontu', '
|
|
151
|
+
return pathJoin(xdg, 'aontu', 'pkg')
|
|
122
152
|
}
|
|
123
153
|
const home = env.HOME
|
|
124
154
|
if ('string' === typeof home && '' !== home) {
|
|
125
|
-
return pathJoin(home, '.cache', 'aontu', '
|
|
155
|
+
return pathJoin(home, '.cache', 'aontu', 'pkg')
|
|
126
156
|
}
|
|
127
157
|
if ('win32' === platform) {
|
|
128
158
|
const local = env.LOCALAPPDATA
|
|
129
159
|
if ('string' === typeof local && '' !== local) {
|
|
130
|
-
return pathJoin(local, 'aontu', '
|
|
160
|
+
return pathJoin(local, 'aontu', 'pkg')
|
|
131
161
|
}
|
|
132
162
|
}
|
|
133
163
|
return undefined
|
|
134
164
|
}
|
|
135
165
|
|
|
136
166
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
167
|
+
// The user cache's trees (ADR-039 part 2).
|
|
168
|
+
export function cacheStoreDir(cache: string, hash: string, pkg: string): string {
|
|
169
|
+
return moduleDir(pathJoin(cache, 'store', hash), pkg)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function cacheDownloadDir(cache: string, pkg: string): string {
|
|
173
|
+
return pathJoin(moduleDir(pathJoin(cache, 'download'), pkg), '@v')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function cacheSeenDir(cache: string, pkg: string): string {
|
|
177
|
+
return moduleDir(pathJoin(cache, 'seen'), pkg)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
export type LockPins = { canon?: string, pkg?: string }
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
export function lockEntry(root: string, key: string, fs: ModuleFs):
|
|
185
|
+
LockPins | undefined {
|
|
186
|
+
const file = pathJoin(root, META_DIR, LOCK_FILE)
|
|
140
187
|
if (!fs.existsSync(file)) {
|
|
141
188
|
return undefined
|
|
142
189
|
}
|
|
@@ -149,8 +196,14 @@ export function lockHash(root: string, ref: ModuleRef, fs: ModuleFs):
|
|
|
149
196
|
return undefined
|
|
150
197
|
}
|
|
151
198
|
|
|
152
|
-
const entry = lock?.lock?.[
|
|
153
|
-
|
|
199
|
+
const entry = lock?.lock?.[key]
|
|
200
|
+
if (null == entry || 'object' !== typeof entry) {
|
|
201
|
+
return undefined
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
...('string' === typeof entry.canon ? { canon: entry.canon } : {}),
|
|
205
|
+
...('string' === typeof entry.pkg ? { pkg: entry.pkg } : {}),
|
|
206
|
+
}
|
|
154
207
|
}
|
|
155
208
|
|
|
156
209
|
|
|
@@ -162,9 +215,9 @@ export const MODULE_MAX_DEPTH = 16
|
|
|
162
215
|
|
|
163
216
|
|
|
164
217
|
export type ModuleOptions = {
|
|
165
|
-
// The content-addressed user cache
|
|
166
|
-
//
|
|
167
|
-
//
|
|
218
|
+
// The content-addressed user cache. Consulted only when the expected
|
|
219
|
+
// hash and the package path are both known, which is what its key
|
|
220
|
+
// is made of.
|
|
168
221
|
cache?: string
|
|
169
222
|
eval: ModuleEval
|
|
170
223
|
// How many module verifications deep this evaluation already is.
|
|
@@ -181,6 +234,7 @@ export type ModuleFound = {
|
|
|
181
234
|
|
|
182
235
|
export const MODULE_REFUSAL_CODES: ReadonlySet<string> = new Set([
|
|
183
236
|
'module_path', 'module_missing', 'module_integrity', 'module_depth',
|
|
237
|
+
'module_local', 'module_moved',
|
|
184
238
|
])
|
|
185
239
|
|
|
186
240
|
|
|
@@ -191,6 +245,12 @@ function refuse(code: string, message: string): never {
|
|
|
191
245
|
}
|
|
192
246
|
|
|
193
247
|
|
|
248
|
+
export function refuseLocalFile(path: string): never {
|
|
249
|
+
return refuse('module_local',
|
|
250
|
+
'local files need a ./ prefix: ' + path + ' (write @"./' + path + '")')
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
194
254
|
// Resolve one module import against the local stores.
|
|
195
255
|
export function resolveModule(
|
|
196
256
|
ref: ModuleRef,
|
|
@@ -198,65 +258,76 @@ export function resolveModule(
|
|
|
198
258
|
fs: ModuleFs,
|
|
199
259
|
options: ModuleOptions,
|
|
200
260
|
): ModuleFound {
|
|
201
|
-
const
|
|
261
|
+
const alias = isAlias(ref.path)
|
|
262
|
+
const badpath = alias ? undefined : validateModulePath(ref.path)
|
|
202
263
|
if (undefined !== badpath) {
|
|
203
|
-
refuse('module_path',
|
|
204
|
-
'module path: ' + ref.path + '@' + ref.major + ' (' + badpath + ')')
|
|
264
|
+
refuse('module_path', 'module path: ' + ref.path + ' (' + badpath + ')')
|
|
205
265
|
}
|
|
206
266
|
|
|
207
267
|
if (MODULE_MAX_DEPTH <= (options.depth ?? 0)) {
|
|
208
268
|
refuse('module_depth',
|
|
209
|
-
'module depth: ' + ref.path +
|
|
269
|
+
'module depth: ' + ref.path +
|
|
210
270
|
' (verification nested past ' + MODULE_MAX_DEPTH + ')')
|
|
211
271
|
}
|
|
212
272
|
|
|
213
273
|
// EVERY enclosing project, innermost first (see projectRoots): a
|
|
214
|
-
// vendored
|
|
274
|
+
// vendored package is a project inside a project, and its nested
|
|
215
275
|
// imports have to reach the tree the consumer vendored them into.
|
|
216
276
|
const roots = projectRoots(fromDir, fs)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
277
|
+
const locked = roots.map((r) => lockEntry(r, ref.path, fs))
|
|
278
|
+
.find((e) => null != e)
|
|
279
|
+
const expect = ref.hash ?? locked?.canon
|
|
280
|
+
// The store is keyed by hash AND package path; an alias names its
|
|
281
|
+
// package in the lockfile, else in the package file that declares it.
|
|
282
|
+
const pkg = alias ?
|
|
283
|
+
(locked?.pkg ?? roots.map((r) => aliasTarget(r, ref.path, fs, options))
|
|
284
|
+
.find((p) => null != p)) : ref.path
|
|
285
|
+
|
|
286
|
+
if (alias && null == pkg) {
|
|
287
|
+
refuse('module_missing',
|
|
288
|
+
'alias not declared: ' + ref.path + ' (declare it under dep in ' +
|
|
289
|
+
PKG_FILE + ')')
|
|
290
|
+
}
|
|
222
291
|
|
|
223
292
|
const stores: string[] =
|
|
224
|
-
roots.map((r) => moduleDir(pathJoin(r,
|
|
293
|
+
roots.map((r) => moduleDir(pathJoin(r, META_DIR, VENDOR_DIR), ref.path))
|
|
225
294
|
if (null != options.cache && null != expect) {
|
|
226
|
-
|
|
227
|
-
// is already the right MEANING before anything is read from it.
|
|
228
|
-
stores.push(pathJoin(options.cache, expect))
|
|
295
|
+
stores.push(cacheStoreDir(options.cache, expect, pkg as string))
|
|
229
296
|
}
|
|
230
297
|
|
|
231
|
-
const dir = stores.find((d) => fs.existsSync(pathJoin(d,
|
|
298
|
+
const dir = stores.find((d) => fs.existsSync(pathJoin(d, PKG_FILE)))
|
|
232
299
|
if (undefined === dir) {
|
|
233
300
|
refuse('module_missing',
|
|
234
|
-
'module not fetched: ' + ref.path + '
|
|
235
|
-
' (run: aontu mod get)')
|
|
301
|
+
'module not fetched: ' + ref.path + ' (run: aontu sync)')
|
|
236
302
|
}
|
|
237
303
|
|
|
238
|
-
// The
|
|
239
|
-
// evaluator rather than a regexp: a
|
|
240
|
-
// and the language reading its own metadata is the
|
|
241
|
-
|
|
242
|
-
const
|
|
304
|
+
// The package's own file names its entry and says whether it moved.
|
|
305
|
+
// Read with the evaluator rather than a regexp: a package file is
|
|
306
|
+
// ordinary Aontu, and the language reading its own metadata is the
|
|
307
|
+
// point.
|
|
308
|
+
const self = packageSelf(pathJoin(dir, PKG_FILE), fs, options)
|
|
309
|
+
if (null != self.moved) {
|
|
310
|
+
refuse('module_moved',
|
|
311
|
+
'module moved: ' + ref.path + ' (now ' + self.moved +
|
|
312
|
+
'; import that instead, nothing follows a move)')
|
|
313
|
+
}
|
|
314
|
+
const full = pathJoin(dir, self.main)
|
|
243
315
|
|
|
244
316
|
if (!fs.existsSync(full)) {
|
|
245
317
|
refuse('module_missing',
|
|
246
|
-
'module not fetched: ' + ref.path + '
|
|
247
|
-
' (run: aontu mod get)')
|
|
318
|
+
'module not fetched: ' + ref.path + ' (run: aontu sync)')
|
|
248
319
|
}
|
|
249
320
|
|
|
250
321
|
const src = fs.readFileSync(full, 'utf8')
|
|
251
322
|
|
|
252
323
|
if (null != expect) {
|
|
253
|
-
// VERIFICATION IS ALWAYS LOCAL. The
|
|
254
|
-
//
|
|
324
|
+
// VERIFICATION IS ALWAYS LOCAL. The repository's manifest is a
|
|
325
|
+
// claim; what decides is the hash of the module as it is on this
|
|
255
326
|
// machine, recomputed now.
|
|
256
327
|
const got = options.eval(src, full).hash
|
|
257
328
|
if (got !== expect) {
|
|
258
329
|
refuse('module_integrity',
|
|
259
|
-
'module integrity: ' + ref.path +
|
|
330
|
+
'module integrity: ' + ref.path +
|
|
260
331
|
' expected ' + expect + ' got ' + got)
|
|
261
332
|
}
|
|
262
333
|
}
|
|
@@ -265,10 +336,30 @@ export function resolveModule(
|
|
|
265
336
|
}
|
|
266
337
|
|
|
267
338
|
|
|
268
|
-
|
|
339
|
+
type PackageSelf = { main: string, moved?: string }
|
|
340
|
+
|
|
341
|
+
function packageSelf(file: string, fs: ModuleFs, options: ModuleOptions):
|
|
342
|
+
PackageSelf {
|
|
343
|
+
const gen: any = options.eval(fs.readFileSync(file, 'utf8'), file).gen
|
|
344
|
+
const main = gen?.pkg?.main
|
|
345
|
+
const moved = gen?.moved
|
|
346
|
+
return {
|
|
347
|
+
main: 'string' === typeof main && '' !== main ? main : DEFAULT_MAIN,
|
|
348
|
+
...('string' === typeof moved && '' !== moved ? { moved } : {}),
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
function aliasTarget(
|
|
354
|
+
root: string, key: string, fs: ModuleFs, options: ModuleOptions,
|
|
355
|
+
): string | undefined {
|
|
356
|
+
const file = pathJoin(root, PKG_FILE)
|
|
357
|
+
if (!fs.existsSync(file)) {
|
|
358
|
+
return undefined
|
|
359
|
+
}
|
|
269
360
|
const gen: any = options.eval(fs.readFileSync(file, 'utf8'), file).gen
|
|
270
|
-
const
|
|
271
|
-
return 'string' === typeof
|
|
361
|
+
const pkg = gen?.dep?.[key]?.pkg
|
|
362
|
+
return 'string' === typeof pkg && '' !== pkg ? pkg : undefined
|
|
272
363
|
}
|
|
273
364
|
|
|
274
365
|
|