diff --git a/CLAUDE.md b/CLAUDE.md index 9c8e94f..6d73cbe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -445,7 +445,7 @@ Implemented entirely in JS — **no tsvm_core changes**. ### Architecture -- **Dispatcher**: `assets/disk0/tvdos/sbin/vtmgr.js`. Launched directly by the +- **Dispatcher**: `assets/disk0/tvdos/VTMGR.SYS`. Launched directly by the `TVDOS.SYS` boot block (only when `!_TVDOS_IS_VT_PANE`); when it exits (Alt-0) the boot block runs `AUTOEXEC.BAT` as the bare fallback shell. Owns the physical keyboard and screen. Each VT runs in its own GraalVM context/thread @@ -525,7 +525,7 @@ arithmetic (no regression outside vtmgr). Applied so far in ### Files -- New: `assets/disk0/tvdos/sbin/vtmgr.js` (dispatcher + per-pane bootstrap) +- New: `assets/disk0/tvdos/VTMGR.SYS` (dispatcher + per-pane bootstrap) - `assets/disk0/tvdos/bin/command.js`: `chvt` builtin, `[N]` prompt prefix for VT 2-6, `shell.stdio.out` → `__VT_OUT` delegation - `assets/disk0/tvdos/TVDOS.SYS`: boot block runs `\commandrc` (env) in every diff --git a/assets/disk0/tvdos/TVDOS.SYS b/assets/disk0/tvdos/TVDOS.SYS index aa17fcb..106a4cd 100644 --- a/assets/disk0/tvdos/TVDOS.SYS +++ b/assets/disk0/tvdos/TVDOS.SYS @@ -1501,7 +1501,7 @@ try { // Boot console: hand the screen to the virtual-console multiplexer. // When it exits (Alt-0), fall through to AUTOEXEC so the console is // never left bare. - runBatch("tvdos/sbin/vtmgr") + runBatch("tvdos/VTMGR.SYS") runBatch("\\AUTOEXEC.BAT") } else { diff --git a/assets/disk0/tvdos/sbin/vtmgr.js b/assets/disk0/tvdos/VTMGR.SYS similarity index 100% rename from assets/disk0/tvdos/sbin/vtmgr.js rename to assets/disk0/tvdos/VTMGR.SYS diff --git a/tvdos_synopses_format_draft.md b/tvdos_synopses_format_draft.md new file mode 100644 index 0000000..652d03d --- /dev/null +++ b/tvdos_synopses_format_draft.md @@ -0,0 +1,651 @@ +# TVDOS Synopses Format (TSF) Version 1.0 Draft + +## 1. Scope + +The TVDOS Synopses Format (TSF) is a machine-readable command interface description language. + +A TSF document describes: + +* Command grammar +* Options and flags +* Positional arguments +* Subcommands +* Argument types +* Completion sources +* Validation constraints + +The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHALL NOT**, **SHOULD**, **SHOULD NOT**, **RECOMMENDED**, **NOT RECOMMENDED**, **MAY**, and **OPTIONAL** in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174) when, and only when, they appear in all capitals. Lowercase uses of these words carry their ordinary English meaning and impose no normative requirement. + +TSF MUST be valid JSON. A TSF document MUST be encoded such that its byte stream contains only ASCII characters: any character outside the ASCII range (U+0000–U+007F) MUST be represented using a JSON `\uXXXX` escape sequence rather than emitted as a literal multibyte character. Consumers MUST decode such escapes per the JSON specification. + +--- + +# 2. Design Goals + +TSF SHALL: + +* Be machine-readable. +* Be human-authorable. +* Support automatic shell completion. +* Support automatic help generation. +* Support parser generation. +* Support GUI generation. + +The structured synopsis grammar SHALL be the sole normative description of command syntax; every other representation, including human-readable usage strings, is treated as generated output derived from it. This principle is referenced rather than restated elsewhere in this document. + +--- + +# 3. Root Object + +A TSF document SHALL contain one JSON object. + +Example: + +```json +{ + "tsfVersion": "1.0", + "name": "cp", + "summary": "Copy files and directories", + "symbols": {}, + "synopsis": {} +} +``` + +--- + +# 4. Root Fields + +| Field | Required | Type | Notes | +| ----------- | -------- | ------ | ------------------------------------------------------------ | +| tsfVersion | yes | string | Version of TSF this document targets. | +| name | yes | string | Command name as invoked. | +| summary | yes | string | One-line description. | +| symbols | yes | object | The symbol table (§5). | +| synopsis | yes | object | The synopsis grammar root node (§12). | +| description | no | string | Free-form long description for help generation. | +| constraints | no | array | Constraint objects (§18). | +| metadata | no | object | Free-form, non-normative data reserved for authors and hosts (§20). | + +--- + +# 5. Symbol Table + +All command elements SHALL be declared in the symbol table. The synopsis grammar SHALL reference symbols by identifier. + +Example: + +```json +{ + "symbols": { + "recursive": { + "kind": "option", + "long": "--recursive", + "short": "-r" + }, + + "source": { + "kind": "positional", + "type": "path" + } + } +} +``` + +--- + +# 6. Symbol Kinds + +Valid symbol kinds: + +```text +option +positional +subcommand +group +``` + +Each kind is defined in §8, §9, §10, and §11 respectively. + +--- + +# 7. Argument Descriptors + +An *argument descriptor* describes a single consumed value. The same descriptor shape is used in two places: directly on a `positional` symbol (§9), and as the `value` of an `option` symbol (§8). Defining it once keeps the two consistent. + +## 7.1 Argument Descriptor Fields + +| Field | Required | Type | Notes | +| ---------- | -------- | -------------- | ---------------------------------------------------------------- | +| type | no | string | One of the built-in types (§15). Defaults to `string`. | +| name | no | string | Metavar shown in generated usage (e.g. `FILE`, `WHEN`). | +| values | cond. | array | Permitted values; **REQUIRED** when `type` is `enum`, otherwise **OPTIONAL** (§15). | +| default | no | any | Default value used for help generation and GUI prefill. | +| validation | no | object | Value-level validation (§7.2). | +| completion | no | object | Completion override (§16). | +| summary | no | string | Short description of the value. | + +Each entry in `values` SHALL be either a bare JSON value, or an object of the form `{ "value": , "summary": }`. The optional per-value `summary` is used for completion hints and help generation. + +## 7.2 Validation Object + +`validation` expresses value-level checks that the grammar cannot: + +| Field | Applies to | Notes | +| --------- | ----------------- | -------------------------------------------------- | +| pattern | string-like types | A regular expression the value MUST match. | +| minimum | numeric types | Inclusive lower bound. | +| maximum | numeric types | Inclusive upper bound. | +| minLength | string-like types | Minimum length in characters. | +| maxLength | string-like types | Maximum length in characters. | + +`pattern` is a regular expression; the supported flavour is implementation-defined, and authors are **RECOMMENDED** to restrict patterns to a portable subset. Because the document is ASCII-only (§1), any non-ASCII character within a pattern MUST be `\u`-escaped. + +--- + +# 8. Option Symbols + +Example: + +```json +{ + "recursive": { + "kind": "option", + "long": "--recursive", + "short": "-r", + "summary": "Copy directories recursively" + } +} +``` + +An option carrying an argument declares it via `value`, which is an argument descriptor (§7): + +```json +{ + "output": { + "kind": "option", + "long": "--output", + "short": "-o", + "summary": "Write output to FILE", + "value": { + "name": "FILE", + "type": "file", + "required": true + } + } +} +``` + +An enumerated option value (the common `--color=WHEN` idiom) makes completion trivial: + +```json +{ + "color": { + "kind": "option", + "long": "--color", + "summary": "Colourise output", + "value": { + "name": "WHEN", + "type": "enum", + "values": [ + { "value": "always", "summary": "Always colourise" }, + { "value": "never", "summary": "Never colourise" }, + { "value": "auto", "summary": "Colourise when stdout is a terminal" } + ], + "default": "auto", + "required": false + } + } +} +``` + +## 8.1 Option Fields + +| Field | Required | Type | Notes | +| --------- | -------- | ------- | --------------------------------------------------------------------- | +| kind | yes | string | `option`. | +| long | cond. | string | Long form, e.g. `--recursive`. | +| short | cond. | string | Short form, e.g. `-r`. | +| summary | no | string | One-line description. | +| value | no | object | Argument descriptor (§7). Omit for a bare flag. | +| negatable | no | boolean | If `true`, a `--no-` form is also accepted. Defaults to `false`. | + +At least one of `long` or `short` SHALL exist. + +The `value` object MAY additionally carry a `required` field (default `true`). When `required` is `true`, the option consumes a mandatory argument; when `false`, the argument is optional (as in `--color` with or without `=WHEN`). + +How many times an option may appear (for example a repeated `-v`) is expressed in the grammar via `repeat` or `oneOrMore` (§13), not by a field on the symbol; this keeps multiplicity in a single place. + +--- + +# 9. Positional Symbols + +A positional symbol is an argument descriptor (§7) plus its `kind`. + +Example: + +```json +{ + "source": { + "kind": "positional", + "type": "path", + "summary": "Source file" + } +} +``` + +## 9.1 Positional Fields + +| Field | Required | Type | Notes | +| ---------- | -------- | ------ | ------------------------------------------- | +| kind | yes | string | `positional`. | +| type | no | string | Built-in type (§15). Defaults to `string`. | +| name | no | string | Metavar shown in generated usage. | +| values | cond. | array | **REQUIRED** when `type` is `enum`. | +| default | no | any | Default value. | +| validation | no | object | Value-level validation (§7.2). | +| completion | no | object | Completion override (§16). | +| summary | no | string | One-line description. | + +Whether a positional is required or optional is expressed in the grammar (by wrapping it in `optional` or not), not by a field here; this keeps a single source of truth. + +--- + +# 10. Subcommand Symbols + +Example: + +```json +{ + "clone": { + "kind": "subcommand", + "summary": "Clone repository", + "tsf": "git.clone" + } +} +``` + +Subcommands MAY reference: + +* embedded TSF documents +* external TSF documents + +Implementation-specific resolution of the `tsf` reference is permitted. + +--- + +# 11. Group Symbols + +A group collects related symbols, typically options, so that the grammar can refer to them collectively. A group is what backs the conventional `[OPTION...]` slot. + +Example: + +```json +{ + "commonOptions": { + "kind": "group", + "summary": "Common options", + "members": [ + "recursive", + "force", + "verbose" + ] + } +} +``` + +## 11.1 Group Fields + +| Field | Required | Type | Notes | +| ------- | -------- | ------ | ------------------------------------------------ | +| kind | yes | string | `group`. | +| members | yes | array | Identifiers of the symbols this group contains. | +| summary | no | string | One-line description. | + +A `reference` to a group (§13) is equivalent to a `choice` over its members. Wrapping that reference in `repeat` yields the familiar "any number of these options, in any order" behaviour of `[OPTION...]`. + +--- + +# 12. Synopsis Grammar + +The synopsis object SHALL describe valid command invocations. + +Every node SHALL contain: + +```json +{ + "type": "" +} +``` + +--- + +# 13. Grammar Node Types + +## sequence + +All children must appear in order. + +```json +{ + "type": "sequence", + "children": [] +} +``` + +Equivalent: + +```text +A B C +``` + +--- + +## choice + +Exactly one child must appear. + +```json +{ + "type": "choice", + "children": [] +} +``` + +Equivalent: + +```text +(A | B | C) +``` + +--- + +## optional + +Child may appear zero or one time. + +```json +{ + "type": "optional", + "child": {} +} +``` + +Equivalent: + +```text +[A] +``` + +--- + +## repeat + +Child may appear zero or more times. + +```json +{ + "type": "repeat", + "child": {} +} +``` + +Equivalent: + +```text +A... +``` + +--- + +## oneOrMore + +Child must appear at least once. This node is sugar for `sequence[A, repeat[A]]` and carries no semantics beyond that combination; it exists for authoring convenience. + +```json +{ + "type": "oneOrMore", + "child": {} +} +``` + +Equivalent: + +```text +A [A...] +``` + +--- + +## reference + +References a symbol. When the referenced symbol is a group, the reference expands to a `choice` over the group's members (§11). + +```json +{ + "type": "reference", + "symbol": "recursive" +} +``` + +--- + +# 14. Example Synopsis + +Human form: + +```text +cp [OPTION...] SOURCE DEST +``` + +Symbol table (abbreviated): + +```json +{ + "symbols": { + "recursive": { "kind": "option", "long": "--recursive", "short": "-r" }, + "force": { "kind": "option", "long": "--force", "short": "-f" }, + "options": { "kind": "group", "members": ["recursive", "force"] }, + "source": { "kind": "positional", "type": "path", "name": "SOURCE" }, + "destination": { "kind": "positional", "type": "path", "name": "DEST" } + } +} +``` + +Synopsis: + +```json +{ + "synopsis": { + "type": "sequence", + "children": [ + { + "type": "repeat", + "child": { + "type": "reference", + "symbol": "options" + } + }, + { + "type": "reference", + "symbol": "source" + }, + { + "type": "reference", + "symbol": "destination" + } + ] + } +} +``` + +The `options` group is a declared symbol, so the `[OPTION...]` slot now satisfies the rule in §5 that every referenced element exists in the symbol table. + +--- + +# 15. Argument Types + +Built-in primitive types: + +```text +string +integer +float +boolean +path +file +directory +url +hostname +user +group +command +enum +``` + +`enum` restricts a value to one of an explicit set; a descriptor whose `type` is `enum` SHALL provide a `values` array (§7.1). The `values` array MAY also be supplied for non-`enum` types as a soft suggestion list, in which case it informs completion but does not restrict valid input. + +Unknown types SHALL be interpreted as `string`. Implementations are **RECOMMENDED** to emit a diagnostic when they do so, since an unknown type is usually an authoring error rather than an intentional fallback. + +Each type carries a default completion behaviour (§16): for example `path`, `file`, and `directory` complete against the filesystem, `user` and `group` against the host's account databases, and `enum` against its `values`. A `completion` block overrides this default. + +--- + +# 16. Completion + +If a descriptor has no `completion` block, completion is derived automatically from its `type` (and from `values` when the type is `enum`). A `completion` block overrides that default. + +| method | Notes | +| -------- | --------------------------------------------------------------------------- | +| type | Use the default completion implied by the descriptor's `type`. (Implicit when no block is present.) | +| enum | Complete from the descriptor's `values`. (Implicit when `type` is `enum`.) | +| internal | Use a named provider resolved by the host. | +| command | Run a command whose output supplies the candidates. | +| list | Offer a static inline list of suggestions, without restricting input. | +| none | Suppress completion for this value. | + +Example using a named internal provider: + +```json +{ + "branch": { + "kind": "positional", + "type": "string", + + "completion": { + "method": "internal", + "provider": "branches" + } + } +} +``` + +--- + +# 17. Constraints + +Constraints describe relationships not expressible in the grammar. They are listed in the root `constraints` array (§4). + +Three of the four constraint types below (`conflicts`, `requires`, `cardinality`) are validation predicates: they describe whether an invocation is well-formed. The fourth, `implies`, is a derivation: it sets a value as a side effect rather than rejecting input. Consumers should treat it accordingly. + +Field naming is uniform: symmetric constraints use `symbols`; asymmetric constraints use `subject` and `targets`. + +--- + +## conflicts + +Symmetric. The listed symbols are mutually exclusive. + +```json +{ + "type": "conflicts", + "symbols": [ + "stdout", + "output" + ] +} +``` + +Meaning: + +```text +--stdout conflicts with --output +``` + +--- + +## requires + +Asymmetric. If `subject` is present, every symbol in `targets` MUST also be present. + +```json +{ + "type": "requires", + "subject": "output", + "targets": [ + "format" + ] +} +``` + +--- + +## implies + +Asymmetric derivation. If `subject` is present, every symbol in `targets` is implicitly set. + +```json +{ + "type": "implies", + "subject": "verbose", + "targets": [ + "log" + ] +} +``` + +--- + +## cardinality + +Symmetric. Constrains how many of the listed symbols may appear. + +```json +{ + "type": "cardinality", + "symbols": [ + "create", + "extract", + "list" + ], + "minimum": 1, + "maximum": 1 +} +``` + +Equivalent: + +```text +exactly one of: +create +extract +list +``` + +--- + +# 18. Generated Usage + +Implementations SHOULD generate usage text from the synopsis grammar. Per §2, that text is non-authoritative output; the grammar remains the sole normative description. + +--- + +# 19. Extensibility and Compatibility + +TSF distinguishes between additive content, which may be ignored safely, and structural content, which may not. + +* **Unknown fields** on otherwise-valid objects SHALL be ignored. Future minor versions MAY add fields without invalidating existing documents or consumers. +* **Unknown grammar node types (§13) and unknown symbol kinds (§6)** SHALL cause the document to be rejected, or to enter an explicitly defined degraded mode. They cannot be ignored, because doing so would silently change the set of accepted invocations. + +Authors and hosts that need to attach implementation-specific data SHOULD do so either inside the root `metadata` object or under field names prefixed with `x-`. Names without that prefix are reserved for future versions of this specification. + +Future TSF versions MAY introduce additional grammar node types, symbol kinds, types, and constraint types. Consumers SHOULD report the highest `tsfVersion` they support so that producers can downgrade gracefully.