aontu 0.55.0 → 0.56.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.
Files changed (84) hide show
  1. package/README.md +3 -3
  2. package/dist/agentsmd.d.ts +1 -0
  3. package/dist/agentsmd.js +10 -3
  4. package/dist/agentsmd.js.map +1 -1
  5. package/dist/aontu.d.ts +3 -2
  6. package/dist/aontu.js +5 -2
  7. package/dist/aontu.js.map +1 -1
  8. package/dist/cli.d.ts +5 -2
  9. package/dist/cli.js +236 -49
  10. package/dist/cli.js.map +1 -1
  11. package/dist/diff.d.ts +1 -0
  12. package/dist/diff.js +3 -2
  13. package/dist/diff.js.map +1 -1
  14. package/dist/format.d.ts +17 -0
  15. package/dist/format.js +1000 -0
  16. package/dist/format.js.map +1 -0
  17. package/dist/hints.js +4 -0
  18. package/dist/hints.js.map +1 -1
  19. package/dist/jsonschema.d.ts +1 -0
  20. package/dist/jsonschema.js +3 -2
  21. package/dist/jsonschema.js.map +1 -1
  22. package/dist/lang.js +64 -5
  23. package/dist/lang.js.map +1 -1
  24. package/dist/lsp.d.ts +2 -1
  25. package/dist/lsp.js +1 -1
  26. package/dist/lsp.js.map +1 -1
  27. package/dist/mcp.js +6 -4
  28. package/dist/mcp.js.map +1 -1
  29. package/dist/patch.d.ts +1 -0
  30. package/dist/patch.js +1 -0
  31. package/dist/patch.js.map +1 -1
  32. package/dist/query.d.ts +1 -0
  33. package/dist/query.js +4 -3
  34. package/dist/query.js.map +1 -1
  35. package/dist/reach.d.ts +1 -0
  36. package/dist/reach.js +3 -2
  37. package/dist/reach.js.map +1 -1
  38. package/dist/relation.d.ts +1 -0
  39. package/dist/relation.js +3 -2
  40. package/dist/relation.js.map +1 -1
  41. package/dist/std.js +2 -1
  42. package/dist/std.js.map +1 -1
  43. package/dist/subsume.d.ts +1 -0
  44. package/dist/subsume.js +3 -2
  45. package/dist/subsume.js.map +1 -1
  46. package/dist/trim.d.ts +1 -0
  47. package/dist/trim.js +3 -2
  48. package/dist/trim.js.map +1 -1
  49. package/dist/tsconfig.tsbuildinfo +1 -1
  50. package/dist/type.d.ts +1 -0
  51. package/dist/type.js.map +1 -1
  52. package/dist/utility.d.ts +8 -2
  53. package/dist/utility.js +9 -1
  54. package/dist/utility.js.map +1 -1
  55. package/dist/vet.d.ts +1 -0
  56. package/dist/vet.js +1 -1
  57. package/dist/vet.js.map +1 -1
  58. package/dist/view.d.ts +2 -1
  59. package/dist/view.js +379 -8
  60. package/dist/view.js.map +1 -1
  61. package/grammar/aontu.abnf +155 -0
  62. package/package.json +2 -1
  63. package/skill/grammar-card.md +5 -2
  64. package/src/agentsmd.ts +15 -3
  65. package/src/aontu.ts +7 -1
  66. package/src/cli.ts +267 -53
  67. package/src/diff.ts +7 -2
  68. package/src/format.ts +1146 -0
  69. package/src/hints.ts +5 -0
  70. package/src/jsonschema.ts +7 -1
  71. package/src/lang.ts +69 -5
  72. package/src/lsp.ts +5 -3
  73. package/src/mcp.ts +6 -4
  74. package/src/patch.ts +7 -0
  75. package/src/query.ts +8 -4
  76. package/src/reach.ts +7 -2
  77. package/src/relation.ts +7 -2
  78. package/src/std.ts +2 -1
  79. package/src/subsume.ts +7 -2
  80. package/src/trim.ts +7 -2
  81. package/src/type.ts +8 -0
  82. package/src/utility.ts +27 -2
  83. package/src/vet.ts +9 -3
  84. package/src/view.ts +442 -9
package/src/hints.ts CHANGED
@@ -192,6 +192,8 @@ const hints: Record<string, string> = {
192
192
  view_kind_unknown: 'The figure kind is not one the verb draws. The kinds are tree, matrix,\ngraph, layer, sets, layers, ladder and poset; the note lists them.',
193
193
 
194
194
  view_profile_unknown: 'The figure kind does not render into the profile asked for: there is no\ntext form of a node-link drawing and no Mermaid form of a matrix. The\nnote lists the profiles the kind declares; the first is its default.',
195
+
196
+ format_check: 'The formatted text is not the same document, so nothing was written.\nThis is a formatter defect: please report it, with the source.',
195
197
  view_style_profile: 'Each profile has ONE way to carry the meaning of a figure\'s marks:\nSGR escapes for text, CSS classes for svg. Asking for the other one is\na usage error rather than a silent no-op. `none` works everywhere.',
196
198
  view_style_unknown: 'The styles are none, ansi and css, plus `auto` at the command line,\nwhich the command resolves before the library runs: whether the\ndestination is a terminal is not something a library can see.',
197
199
 
@@ -513,6 +515,9 @@ const codeClasses: Record<string, string> = {
513
515
  view_profile_unknown: 'reference',
514
516
  view_style_profile: 'reference',
515
517
  view_style_unknown: 'reference',
518
+ // The formatter's self-check (docs/design/FMT.0.md): a report-layer
519
+ // code, class internal -- the formatter, not the document, is wrong.
520
+ format_check: 'internal',
516
521
  view_rows_exceeded: 'budget',
517
522
  view_line_break: 'parse',
518
523
  view_relation_ambiguous: 'reference',
package/src/jsonschema.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // JSON SCHEMA EXPORT (the review's finding I / SUPPORT.md act 2).
4
5
  //
@@ -75,6 +76,11 @@ export type SchemaOptions = {
75
76
  // its own directory.
76
77
  path?: string
77
78
  trust?: TrustOptions
79
+
80
+ // Extensions additionally read as text (the CLI's `--text-ext`).
81
+ // Rides beside `trust` because it is the other half of what an
82
+ // include may read.
83
+ textExt?: string[]
78
84
  }
79
85
 
80
86
 
@@ -501,7 +507,7 @@ function fromList(ctx: Ctx, path: string[], v: any): any {
501
507
  // The verb. Evaluate, anchor, walk, report.
502
508
  export function jsonSchema(src: string, options?: SchemaOptions): SchemaReport {
503
509
  const opts = options ?? {}
504
- const aontu = new Aontu(null == opts.trust ? {} : { trust: opts.trust })
510
+ const aontu = new Aontu(includeOpts(opts))
505
511
 
506
512
  // COLLECT MODE, so a syntax error arrives on the context rather than
507
513
  // as a throw -- the same failure Go's `parseEntry` hands back as an
package/src/lang.ts CHANGED
@@ -1597,6 +1597,14 @@ help isolate the syntax error.`,
1597
1597
  // references, constraints, its own includes. Two extensions, and they
1598
1598
  // are the ones this project owns.
1599
1599
  //
1600
+ // `text` — the file's BYTES, as one string scalar. No parser is
1601
+ // chosen, so there is nothing for two ports to disagree about and
1602
+ // nothing in the file that can mean anything: `notes: @"notes.txt"`
1603
+ // is a document loading prose into a string. `.txt` is the only
1604
+ // extension here by default; `AontuOptions.textExt` (the CLI's
1605
+ // `--text-ext`) adds others, because which name a project keeps its
1606
+ // templates under is the project's business, not this table's.
1607
+ //
1600
1608
  // A FORMAT NAME — configuration DATA, parsed by that format's own
1601
1609
  // parser into the JSON value it denotes, which then becomes Aontu
1602
1610
  // values like any other data. Every one of these formats maps onto
@@ -1628,8 +1636,43 @@ const INCLUDE_KINDS: { [kind: string]: string } = {
1628
1636
  yaml: 'yaml',
1629
1637
  yml: 'yaml',
1630
1638
  ini: 'ini',
1639
+
1640
+ txt: 'text',
1641
+ }
1642
+
1643
+
1644
+ // WHAT AN EXTENSION MEANS, for this parse. The table is the fixed
1645
+ // part; `textExt` is the per-parse widening, and it wins over nothing
1646
+ // -- a host cannot re-read `.toml` as text, because an extension the
1647
+ // table already names has a meaning documents rely on. Undefined is
1648
+ // the refusal, and it is the ONE place that decides it: the resolver's
1649
+ // gate and the processor map both ask here, so a widening cannot reach
1650
+ // one and not the other.
1651
+ function includeFormat(
1652
+ ext: string, textExt?: string[]): string | undefined {
1653
+ const known = INCLUDE_KINDS[ext]
1654
+ if (undefined !== known) {
1655
+ return known
1656
+ }
1657
+ // NOT EVEN AS TEXT. `.js` is the extension ADR-012 singles out
1658
+ // because multisource's own default EXECUTES it, and an extension
1659
+ // this project refuses on purpose stays refused however a flag is
1660
+ // spelled -- reading it is harmless, but a widening that can reach
1661
+ // the one name the rule names is a widening whose limit nobody can
1662
+ // state. Go's includeFormat holds the same list, and the two CLIs
1663
+ // are diffed on `--text-ext js` because they once disagreed here.
1664
+ if (REFUSED_EXT.has(ext)) {
1665
+ return undefined
1666
+ }
1667
+ return textExt?.includes(ext) ? 'text' : undefined
1631
1668
  }
1632
1669
 
1670
+
1671
+ // Extensions no widening may reach. `js` executes under multisource's
1672
+ // default processor; `''` is the no-extension fallback, which names no
1673
+ // file type at all.
1674
+ const REFUSED_EXT = new Set(['js', ''])
1675
+
1633
1676
  // `.csv` IS DELIBERATELY ABSENT, and the reason is ADR-001 rather than
1634
1677
  // taste. The two ports' CSV parsers disagree about what a CSV file IS:
1635
1678
  // one answers header-keyed records with string fields, the other raw
@@ -1754,13 +1797,20 @@ const dataProcessor = (format: string) => (res: any) => {
1754
1797
  res.val = rawToVal(DATA_READERS[format](res.src, res.path))
1755
1798
  }
1756
1799
 
1800
+ // TEXT IS NOT PARSED. The bytes multisource read are the value, so
1801
+ // this is the one processor with no reader behind it -- which is why
1802
+ // a `.txt` include cannot fail on content, only on being unreadable.
1803
+ const textProcessor = (res: any) => {
1804
+ res.val = new StringVal({ peg: res.src })
1805
+ }
1806
+
1757
1807
  /**
1758
1808
  * The multisource processor map, built FROM the include table so the
1759
1809
  * two cannot drift: every extension the table names gets the reader
1760
1810
  * the table names for it, and the two kinds that are not in the table
1761
1811
  * refuse.
1762
1812
  */
1763
- function includeProcessors(): { [kind: string]: any } {
1813
+ function includeProcessors(textExt?: string[]): { [kind: string]: any } {
1764
1814
  const map: { [kind: string]: any } = {
1765
1815
  // multisource's fallback for an extension no entry names, so it is
1766
1816
  // the one that catches whatever the resolver's gate did not.
@@ -1769,9 +1819,23 @@ function includeProcessors(): { [kind: string]: any } {
1769
1819
  js: refuseProcessor,
1770
1820
  }
1771
1821
  const source = makeJsonicProcessor()
1822
+ const forKind = (kind: string) => {
1823
+ const format = includeFormat(kind, textExt)
1824
+ if ('source' === format) return source
1825
+ if ('text' === format) return textProcessor
1826
+ return dataProcessor(format as string)
1827
+ }
1772
1828
  for (const kind of Object.keys(INCLUDE_KINDS)) {
1773
- const format = INCLUDE_KINDS[kind]
1774
- map[kind] = 'source' === format ? source : dataProcessor(format)
1829
+ map[kind] = forKind(kind)
1830
+ }
1831
+ // A WIDENING NEVER OVERWRITES. `js` and the empty fallback refuse
1832
+ // above and stay refusing: `--text-ext js` would otherwise turn the
1833
+ // one extension ADR-012 singles out into a readable one, by a flag
1834
+ // whose whole promise is that it chooses no parser.
1835
+ for (const ext of textExt ?? []) {
1836
+ if (undefined === map[ext]) {
1837
+ map[ext] = textProcessor
1838
+ }
1775
1839
  }
1776
1840
  return map
1777
1841
  }
@@ -1893,7 +1957,7 @@ function makeModelResolver(options: any) {
1893
1957
  // module legs do not: both state `kind: 'aon'` because what they
1894
1958
  // serve is Aontu source by construction, not by its spelling.
1895
1959
  const gateExtension = (path: string, full: string): void => {
1896
- if (undefined === INCLUDE_KINDS[extKindOf(full)]) {
1960
+ if (undefined === includeFormat(extKindOf(full), options.textExt)) {
1897
1961
  refuseExtension(path, full)
1898
1962
  }
1899
1963
  }
@@ -2308,7 +2372,7 @@ class Lang {
2308
2372
  // (BUGS §49b). Its `js` entry EXECUTES the file, which is not
2309
2373
  // something an extension should be able to ask for. And its
2310
2374
  // fallback hands any other file back as TEXT.
2311
- processor: includeProcessors()
2375
+ processor: includeProcessors(this.opts.textExt)
2312
2376
  })
2313
2377
  .use(AontuJsonic)
2314
2378
  }
package/src/lsp.ts CHANGED
@@ -21,7 +21,9 @@ import type { Val } from './type'
21
21
  import { Aontu, VERSION } from './aontu'
22
22
  import { getHint } from './err'
23
23
  import { collectNils } from './walk'
24
- import { collectDeprecations, deprecationMessage } from './utility'
24
+ import { collectDeprecations, deprecationMessage,
25
+ includeOpts,
26
+ } from './utility'
25
27
  import { why } from './query'
26
28
  import type { WhyConjunct } from './provenance'
27
29
 
@@ -84,13 +86,13 @@ type OutMessage = {
84
86
  // functions, syntax errors) produce diagnostics.
85
87
  function computeDiagnostics(
86
88
  src: string,
87
- opts?: { vars?: Record<string, Val>, trust?: any }
89
+ opts?: { vars?: Record<string, Val>, trust?: any, textExt?: string[] }
88
90
  ): Diagnostic[] {
89
91
  // The trust profile (G5, docs/trust.md): the LSP is the
90
92
  // highest-exposure surface — merely OPENING a hostile .aon file in an
91
93
  // editor performs its reads — so the handler confines evaluation to
92
94
  // the workspace root and threads the profile through here.
93
- const aontu = new Aontu(null == opts?.trust ? {} : { trust: opts.trust })
95
+ const aontu = new Aontu(includeOpts(opts ?? {}))
94
96
 
95
97
  let root: any
96
98
  let ac: any
package/src/mcp.ts CHANGED
@@ -459,6 +459,8 @@ const TOOLS: ToolDef[] = [
459
459
  name: 'view',
460
460
  description:
461
461
  'Draw a figure of the document as deterministic text. Kinds: ' +
462
+ 'doc (the shape of the document itself), lattice (the value ' +
463
+ 'lattice, with the document\'s own values placed on it), ' +
462
464
  'tree (the dependency tree of a relation), matrix (the ' +
463
465
  'dependency matrix, canon or partition order, --closure), graph ' +
464
466
  '(node-link, as mermaid, dot or er), layer (the architecture ' +
@@ -474,8 +476,8 @@ const TOOLS: ToolDef[] = [
474
476
  kind: {
475
477
  type: 'string',
476
478
  description:
477
- 'The figure to draw: tree (the default), matrix, graph, layer, ' +
478
- 'sets, layers or ladder',
479
+ 'The figure to draw: tree (the default), doc, lattice, matrix, ' +
480
+ 'graph, layer, sets, layers or ladder',
479
481
  },
480
482
  as: {
481
483
  type: 'string',
@@ -565,8 +567,8 @@ const TOOLS: ToolDef[] = [
565
567
  required: ['source'],
566
568
  docs: ['source'],
567
569
  check: (a) => {
568
- const kinds = ['doc', 'tree', 'matrix', 'graph', 'layer', 'sets',
569
- 'layers', 'ladder']
570
+ const kinds = ['doc', 'lattice', 'tree', 'matrix', 'graph', 'layer',
571
+ 'sets', 'layers', 'ladder']
570
572
  if (null != a.kind && !kinds.includes(a.kind)) {
571
573
  return `kind must be one of ${kinds.join(', ')}, not ${JSON.stringify(a.kind)}`
572
574
  }
package/src/patch.ts CHANGED
@@ -75,6 +75,12 @@ export type PatchOptions = {
75
75
  // The include capability this document evaluates under
76
76
  // (G5, docs/trust.md); vet's precedent.
77
77
  trust?: TrustOptions
78
+ // The extensions an include additionally reads as text (the CLI's
79
+ // --text-ext). It rides WITH the capability, never beside it: this
80
+ // verb threaded the capability and not the extension, so `set`
81
+ // refused an include -- and wrote nothing -- under a flag the bare
82
+ // command honoured.
83
+ textExt?: string[]
78
84
  }
79
85
 
80
86
 
@@ -578,6 +584,7 @@ export function patch(
578
584
  // the caller, "which file" is the whole question.
579
585
  const report: VetReport = vet(entrySrc, overlay, {
580
586
  trust: options.trust,
587
+ textExt: options.textExt,
581
588
  schemaPath: options.entryPath,
582
589
  dataPath: options.overlayPath,
583
590
  schemaUrl: options.entryPath,
package/src/query.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // THE QUERY SURFACE (G7 phase 1,
4
5
  // docs/capability-review/g7-machine-access.md): select one node of an
@@ -56,6 +57,11 @@ export type QueryOptions = {
56
57
  // extension -- but reading is enough.) A server passes
57
58
  // `{include:'none'}`.
58
59
  trust?: TrustOptions
60
+
61
+ // Extensions additionally read as text (the CLI's `--text-ext`).
62
+ // Rides beside `trust` because it is the other half of what an
63
+ // include may read.
64
+ textExt?: string[]
59
65
  }
60
66
 
61
67
  export type QueryReport = {
@@ -271,8 +277,7 @@ export function get(
271
277
  const options = opts ?? {}
272
278
  const view: QueryView = options.view ?? 'json'
273
279
 
274
- const aontu = new Aontu(
275
- null == options.trust ? undefined : { trust: options.trust })
280
+ const aontu = new Aontu(includeOpts(options))
276
281
  const ctx = aontu.ctx({ collect: true })
277
282
  const parseOpts = null == options.path ? undefined : { path: options.path }
278
283
  const root: any = aontu.unify(src, parseOpts, ctx)
@@ -336,8 +341,7 @@ export type WhyReport = {
336
341
  export function why(
337
342
  src: string, path: string, opts?: QueryOptions): WhyReport {
338
343
  const options = opts ?? {}
339
- const aontu = new Aontu(
340
- null == options.trust ? undefined : { trust: options.trust })
344
+ const aontu = new Aontu(includeOpts(options))
341
345
  const prov = new Provenance()
342
346
  const ctx = aontu.ctx({ collect: true, prov })
343
347
  const parseOpts = null == options.path ? undefined : { path: options.path }
package/src/reach.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // REACHABILITY OVER THE LINK GRAPH (the review's finding J,
4
5
  // use-cases/REVIEW.md): "ship a transitive `reaches(a, b)` check verb".
@@ -60,6 +61,11 @@ export type ReachOptions = {
60
61
  // The include capability this document evaluates under (G5,
61
62
  // docs/trust.md).
62
63
  trust?: TrustOptions
64
+
65
+ // Extensions additionally read as text (the CLI's `--text-ext`).
66
+ // Rides beside `trust` because it is the other half of what an
67
+ // include may read.
68
+ textExt?: string[]
63
69
  // Follow only edges under this relation. Absent means follow every
64
70
  // edge, which is the whole graph and the commoner question.
65
71
  relation?: string
@@ -124,8 +130,7 @@ export function reachCheck(
124
130
  src: string, from: string, to: string, opts?: ReachOptions
125
131
  ): ReachReport {
126
132
  const options = opts ?? {}
127
- const aontu = new Aontu(
128
- null == options.trust ? undefined : { trust: options.trust })
133
+ const aontu = new Aontu(includeOpts(options))
129
134
  const ctx = aontu.ctx({ collect: true })
130
135
  const parseOpts = null == options.path ? undefined : { path: options.path }
131
136
  const root: any = aontu.unify(src, parseOpts, ctx)
package/src/relation.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // RELATION GRAPH VERDICTS (RELATIONS.0.md §3.3, replacing the G4
4
5
  // phase 5 magic-key pass): acyclicity and inverse consistency over
@@ -70,6 +71,11 @@ export type RelationOptions = {
70
71
  // docs/trust.md). vet's precedent: the verb passes the profile the
71
72
  // caller asked for, and an absent option means today's default.
72
73
  trust?: TrustOptions
74
+
75
+ // Extensions additionally read as text (the CLI's `--text-ext`).
76
+ // Rides beside `trust` because it is the other half of what an
77
+ // include may read.
78
+ textExt?: string[]
73
79
  }
74
80
 
75
81
 
@@ -248,8 +254,7 @@ export function relationErrors(ctx: any, root: any): void {
248
254
  export function relationCheck(
249
255
  src: string, opts?: RelationOptions): RelationReport {
250
256
  const options = opts ?? {}
251
- const aontu = new Aontu(
252
- null == options.trust ? undefined : { trust: options.trust })
257
+ const aontu = new Aontu(includeOpts(options))
253
258
  const ctx = aontu.ctx({ collect: true })
254
259
  const parseOpts = null == options.path ? undefined : { path: options.path }
255
260
  const root: any = aontu.unify(src, parseOpts, ctx)
package/src/std.ts CHANGED
@@ -87,7 +87,8 @@ view: {
87
87
  # it belongs; everything else narrows the drawing, and each option
88
88
  # belongs to the kinds that read it.
89
89
  Figure: type({
90
- kind: doc | tree | matrix | graph | layer | sets | layers | ladder
90
+ kind: doc | lattice | tree | matrix | graph | layer | sets | layers
91
+ | ladder
91
92
  out: string
92
93
 
93
94
  # Every kind.
package/src/subsume.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // Subsumption as a first-class query (G3 phases 1-2,
4
5
  // docs/capability-review/g3-subsumption-evolution.md): does the GENERAL
@@ -55,6 +56,11 @@ export type SubsumeOptions = {
55
56
  // docs/trust.md). vet's precedent: the verb passes the profile the
56
57
  // caller asked for, and an absent option means today's default.
57
58
  trust?: TrustOptions
59
+
60
+ // Extensions additionally read as text (the CLI's `--text-ext`).
61
+ // Rides beside `trust` because it is the other half of what an
62
+ // include may read.
63
+ textExt?: string[]
58
64
  }
59
65
 
60
66
  export type SubsumeReport = {
@@ -699,8 +705,7 @@ export function subsume(
699
705
  }
700
706
 
701
707
  const load = (src: string, path?: string): any => {
702
- const aontu = new Aontu(
703
- null == options.trust ? undefined : { trust: options.trust })
708
+ const aontu = new Aontu(includeOpts(options))
704
709
  const ctx = aontu.ctx({ collect: true })
705
710
  const v: any = aontu.unify(
706
711
  src, null == path ? undefined : { path }, ctx)
package/src/trim.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+ import { includeOpts } from './utility'
2
3
 
3
4
  // The trim reporter (G3 phase 6,
4
5
  // docs/capability-review/g3-subsumption-evolution.md): report REDUNDANT
@@ -50,6 +51,11 @@ export type TrimOptions = {
50
51
  // docs/trust.md). vet's precedent: the verb passes the profile the
51
52
  // caller asked for, and an absent option means today's default.
52
53
  trust?: TrustOptions
54
+
55
+ // Extensions additionally read as text (the CLI's `--text-ext`).
56
+ // Rides beside `trust` because it is the other half of what an
57
+ // include may read.
58
+ textExt?: string[]
53
59
  }
54
60
 
55
61
 
@@ -119,8 +125,7 @@ export function deleteAt(root: any, path: string[]): boolean {
119
125
  export function evalCanon(
120
126
  src: string, opts: TrimOptions, delPath?: string[],
121
127
  sink?: { ctx?: any, failed?: any }): string | undefined {
122
- const aontu = new Aontu(
123
- null == opts.trust ? undefined : { trust: opts.trust })
128
+ const aontu = new Aontu(includeOpts(opts))
124
129
  const ctx = aontu.ctx({ collect: true })
125
130
  const parseOpts = null == opts.path ? undefined : { path: opts.path }
126
131
  // WHY the run failed, for the one caller that reports it. The
package/src/type.ts CHANGED
@@ -69,6 +69,14 @@ type AontuOptions = {
69
69
  explain?: any[]
70
70
  trust?: TrustOptions // Trust profile (G5, docs/trust.md)
71
71
 
72
+ // EXTENSIONS ADDITIONALLY READ AS TEXT, without their dots. `.txt`
73
+ // is read as text with no option at all; this widens that set for a
74
+ // host that keeps its prose in `.md`, its queries in `.sql`, or its
75
+ // templates under some name only it knows. The file's bytes become
76
+ // one string scalar -- no parser is chosen for it, which is what
77
+ // makes widening the set safe to offer.
78
+ textExt?: string[]
79
+
72
80
  // The staged-flip warning window (G5 phase 6, CLI only): under the
73
81
  // default 'system' capability the CLI supplies these, and the
74
82
  // resolver calls trustWarn for every resolution that escapes
package/src/utility.ts CHANGED
@@ -2,7 +2,29 @@
2
2
 
3
3
 
4
4
 
5
- import type { Val } from './type'
5
+ import type { AontuOptions, TrustOptions, Val } from './type'
6
+
7
+
8
+ // THE INCLUDE OPTIONS AN ENGINE HANDS ITS Aontu INSTANCE. Every verb
9
+ // engine builds one, and until there were two such options each did it
10
+ // inline -- `null == options.trust ? undefined : { trust: options.trust }`,
11
+ // written out twelve times. That is fine while there is one option and
12
+ // a latent bug the moment there are two: `textExt` had to reach the
13
+ // same twelve places, and the one it missed refused a `.md` include
14
+ // under a flag the bare command honoured. One function now, so a third
15
+ // include option is threaded once.
16
+ type IncludeOptions = {
17
+ trust?: TrustOptions
18
+ textExt?: string[]
19
+ }
20
+
21
+ function includeOpts(options: IncludeOptions): Partial<AontuOptions> {
22
+ return {
23
+ ...(null == options.trust ? {} : { trust: options.trust }),
24
+ ...(null == options.textExt || 0 === options.textExt.length
25
+ ? {} : { textExt: options.textExt }),
26
+ }
27
+ }
6
28
 
7
29
 
8
30
  // Default walk() depth limit. High enough that real configs are never
@@ -262,10 +284,13 @@ function items(o: any) {
262
284
  else {
263
285
  return []
264
286
  }
265
- } /* node:coverage ignore next 18 */
287
+ } /* node:coverage ignore next 20 */
288
+
266
289
 
290
+ export type { IncludeOptions }
267
291
 
268
292
  export {
293
+ includeOpts,
269
294
  items,
270
295
  propagateMarks,
271
296
  canonRiders,
package/src/vet.ts CHANGED
@@ -36,7 +36,9 @@ import { descErr, getHint } from './err'
36
36
  import { ConjunctVal } from './val/ConjunctVal'
37
37
  import { walkVals, collectNils } from './walk'
38
38
  import { sizingResidue } from './val/BagVal'
39
- import { collectDeprecations, walkBagVals, deprecationMessage } from './utility'
39
+ import { collectDeprecations, walkBagVals, deprecationMessage,
40
+ includeOpts,
41
+ } from './utility'
40
42
  import { subsumeNode, effectiveDefault } from './subsume'
41
43
  // The `--at` refusal is the SAME refusal `get` and `why` give for a
42
44
  // path that names nothing, down to the "did you mean" -- so it is that
@@ -151,6 +153,11 @@ export type VetOptions = {
151
153
  // ADR-012 refuses the extension -- but reading is enough.) A server
152
154
  // passes `{include:'none'}`.
153
155
  trust?: TrustOptions
156
+
157
+ // Extensions additionally read as text (the CLI's `--text-ext`).
158
+ // Rides beside `trust` because it is the other half of what an
159
+ // include may read.
160
+ textExt?: string[]
154
161
  }
155
162
 
156
163
 
@@ -599,8 +606,7 @@ export function vet(
599
606
  // ONE instance, two bases: the path rides on each CALL rather than on
600
607
  // the constructor, because the schema and the data may live in
601
608
  // different directories (Lang.parse takes `opts.path` per parse).
602
- const aontu = new Aontu(
603
- null == options.trust ? undefined : { trust: options.trust })
609
+ const aontu = new Aontu(includeOpts(options))
604
610
  const schemaOpts = null == options.schemaPath ?
605
611
  undefined : { path: options.schemaPath }
606
612
  const dataOpts = null == options.dataPath ?