# MSet Instruction Author 04 - Safe editing and error handling

Status: **canonical-development**
Branch: **MSet 64-bit**
Current product: **MSet 2026 by GRAPHICO**
Format covered: **MSet 2026 native instruction format 2026.1 plus legacy-readable packages**

## Purpose

This is the fourth required module for an LLM that will read, explain, validate, create, or modify an MSet 64-bit instruction.

Modules 01-03 define the package model, command composition, and standard scale/substitution behavior. This module defines the **editing discipline**: how to make a requested change without silently damaging package structure, Signum, encoding, inheritance, scale behavior, or unrelated commands, and how to classify and recover from common failures.

Modules 01-04 establish the technical authoring and editing contract. Module 05 adds the required authoring-practice layer. After completing modules 01-05, the Instruction Author track is considered complete for **current MSet 2026 standard-mode instruction authoring**. That readiness has explicit boundaries: it does not certify arbitrary Bentley/application key-ins, Annotation Scale behavior, or historical `$M(...)` control macros.

## Source authority

Use the same authority order as the earlier modules:

1. current MSet 2026 runtime/parser behavior and current contract tests,
2. current MSet 2026 specifications and accepted project decisions,
3. current runtime-verified MSet 2026 instruction packages,
4. MSet 10 manual and other legacy documentation.

Current source checkpoint used by this track: MSet 2026 version `26.11.0.4`.

Relevant current implementation/contract areas include the instruction parser/model, DTD/entity resolution, command composer, substitution engine and runtime-verified `MSet_Polohopis` package. The legacy manual is useful as supporting evidence that XML-aware editing and direct host key-in testing are valid debugging techniques; it does not override current parser/runtime rules.

Do not import 32-bit/V8i editing rules into this branch.

## 1. The prime editing rule: change the real source, not the expanded appearance

An MSet instruction can be a multi-file XML package. Before changing anything:

1. identify the entry XML,
2. inspect its XML declaration and DTD/entity declarations,
3. follow relevant external entity/include references,
4. locate the file that actually owns the requested content,
5. determine whether that content is reused elsewhere,
6. make the smallest semantic change in that real source file.

A command or node visible after XML entity expansion may originate in `.ent` or `.ixml`, not in the entry XML.

### Shared-entity consequence

If one entity definition is reused by several nodes, editing the entity changes **every use** of that entity. Before editing a reusable fragment, inspect its references and decide whether the requested change is global or local.

For a local-only change, do not casually modify a shared entity. Prefer a deliberate local override/refactor that preserves valid package structure and is checked for all affected references.

## 2. Preserve package identity unless the user asked to change it

During an ordinary edit, preserve:

- the entry XML filename,
- directory layout required by relative references,
- DTD/entity/include relationships,
- existing file encoding,
- `FormatVersion` mode,
- unrelated nodes and commands.

### Entry filename and Signum

The entry XML filename determines Signum.

```text
MSet_Polohopis.xml -> MSET_POLOHOPIS
```

Renaming the entry XML is therefore a semantic change, not cosmetic cleanup. It can break the expected instruction identity/DGN association. Do not rename it unless the requested change intentionally includes a Signum change and the caller understands the consequence.

## 3. Preserve encoding and XML declaration coherently

Existing package files may use different historical encodings. The current runtime-verified `MSet_Polohopis` package uses `windows-1250`.

Canonical editing rule:

- preserve each existing file's encoding during routine editing,
- keep the XML encoding declaration consistent with the actual bytes,
- do not convert a package to UTF-8 merely because the editor or LLM prefers UTF-8,
- perform an encoding migration only when explicitly requested and then validate the complete package.

A package that was logically correct before an edit can become unreadable if the file bytes and XML encoding declaration no longer agree.

## 4. Preserve format mode; do not silently migrate legacy instructions

Current native format:

```xml
FormatVersion="2026.1"
```

Rules:

- existing `FormatVersion="2026.1"` -> preserve it unless a deliberate format change is requested,
- missing `FormatVersion` -> accepted legacy compatibility mode; do not automatically insert `2026.1` during unrelated cleanup,
- unsupported non-empty `FormatVersion` -> do not guess a replacement; report the incompatibility or perform an explicit, reviewed migration.

For a newly created modern MSet 2026 instruction, use `FormatVersion="2026.1"`.

### From-scratch native authoring acceptance rules

When creating a new MSet 2026 instruction from scratch, apply these acceptance rules:

- **a DTD is mandatory**,
- if the requested artifact is one self-contained XML file with no support files, embed the DTD as an internal subset,
- do not confuse "single file" with "no DTD",
- inside each newly authored `Group`, normally place nested Groups before direct Features,
- keep the Group's own command fragment before its first child,
- establish a deterministic drawing-state baseline at the nearest useful common Group when the descendants depend on active graphical attributes,
- use only key-ins with adequate evidence; plausible-looking host commands are not enough.

The **Groups-first rule is an authoring convention**, not a parser restriction. The **DTD rule is a product authoring requirement**: do not create or return a DTD-less MSet instruction. A permissive parser accepting some DTD-less XML would not make that XML canonical or valid for MSet authoring.

### Artifact delivery convention

The finished instruction/package is delivered as a file artifact, not only as XML pasted into chat:

- one self-contained instruction file -> deliver the `.xml` file,
- multi-file instruction/package -> deliver a `.zip` that preserves the required relative directory structure,
- the attached file/package is the authoritative deliverable; inline text is explanatory/review material.

This convention does not change the MSet parser contract. It prevents copy/paste damage to encoding, DTD/entity relationships and package layout, and it scales naturally from one-file examples to entity/include packages.

### Artifact handoff integrity

Before reporting an authoring/editing task as finished, verify the **exact artifact that will be returned to the user**, not only a temporary working copy:

1. reopen/read the final `.xml` or the entry XML inside the final `.zip`,
2. verify that the requested semantic change is actually present,
3. verify that unrelated content which should have been preserved is still present,
4. verify that required DTD/entity/include/support-file relationships remain resolvable in the delivered artifact,
5. do not claim completion if the file being attached/returned is an older or original copy that does not contain the requested change.

If the tool/client creates several similarly named copies, the artifact selected for delivery must be the one that passed this final verification. A statement such as "done" or "updated" is not sufficient evidence that the returned file is the edited file.

### Continuation after a task-specific re-upload

Once the requested task is already established, a newly supplied or re-supplied task-specific XML/package is normally the **current input revision for the same task**. Continue the established task against that newest supplied revision unless:

- the user explicitly changes the requested task,
- the new file conflicts with the established task in a way that changes the intended result, or
- the required target becomes genuinely ambiguous.

Do not ask "what should I do with this file?" merely because the user re-uploaded the original/current instruction after an earlier attempt. If the newest supplied revision does not contain the still-requested change, apply that change to the newest revision and then perform the final artifact verification above.

## 5. Structural invariants that an edit must not break

The current parser/format contract requires the structural rules taught in module 01. Important checks include:

- root element is `Instruction`,
- `Page`, `Group`, and `Feature` require `Cpt`,
- `Feature` is a leaf and must not gain child instruction nodes,
- `Group` may contain nested Group/Feature nodes,
- at most one `<Scales>` element,
- when `<Scales>` exists, `PrimaryScale` and every listed value are positive integers,
- `PrimaryScale` must occur in the declared scale list,
- every instruction must have a DTD; external DTD/entity/include resources must remain resolvable.

Do not edit the DTD merely to make an invented element or attribute appear valid. A DTD change is itself a format-contract change and requires deliberate review.

### Valid things that must not be "cleaned up" as errors

These are valid and should not be changed merely for aesthetics:

- missing `<Scales>` (runtime defaults are valid),
- missing `FormatVersion` in a legacy-readable instruction,
- empty local Group/Feature command fragments,
- repeated `Cpt` captions,
- entity-based reuse of command fragments or complete node fragments.

## 6. Identify nodes by structural path, not caption alone

`Cpt` is display text, not a guaranteed unique technical ID.

Bad edit instruction:

```text
Change Feature "Hranica parcely".
```

Safer identification:

```text
Page "Kreslenie"
-> Group "400 Kataster nehnutelnosti"
-> Group "402 UO"
-> Feature "Hranica parcely"
```

When captions repeat, inspect the surrounding hierarchy and command content before selecting the edit target.

## 7. Preserve command scope while editing

Before changing command text, classify where it lives:

```text
Instruction command -> instruction lifecycle
Page command        -> page lifecycle
Group command       -> inherited Feature prefix/scope
Feature command     -> selected executable leaf
```

Do not move a command between these scopes merely to make the XML look simpler. Moving text from a Group into one Feature, for example, changes all sibling Features that previously inherited it.

For Feature behavior, reason about the complete effective command:

```text
highest ancestor Group
-> nested Group(s)
-> selected Feature
```

Instruction/Page lifecycle commands are not part of that inherited chain.

## 8. Command-editing hazards from modules 02 and 03

A safe editor must preserve these current rules:

### `$C`

`$C` suppresses the composition boundary semicolon after its fragment. It does **not** create a joining space.

Do not change:

```text
place text $C
```

to:

```text
place text$C
```

unless concatenation without a space is intentionally required.

### `$X`

`$X` discards the accumulated prefix before the **last** `$X`. Adding, deleting, or moving an `$X` can change the whole inherited command, not only the local fragment.

### `$S(...)`

`$S(number)` runs before automatic scale-sensitive substitutions. Do not wrap an already automatically scaled assignment (`tx/th/tw/ls`, `PS/PD`, explicit `AS`, explicit `TS`) in `$S(...)` unless deliberate double scaling is required and verified.

### `$M(...)`

Historical `$M(...)` semantics are not current canonical MSet 2026 authoring guidance. Do not generate or "repair" `$M(...)` from legacy documentation.

## 9. Key-ins: MSet transport is not proof that a command is valid

MSet ultimately dispatches resulting key-ins to the active Bentley host/application. The existence of a string in an instruction does not prove that the host knows it.

When authoring or modifying a key-in:

- use a documented Bentley/application command, a GRAPHICO runtime-verified command, an existing known-working package command, or explicit user-supplied syntax,
- preserve the target product/application context,
- do not invent a plausible-looking key-in,
- if validity is uncertain, mark it unverified and request/perform host-side verification.

Legacy documentation also gives a useful debugging principle: a normal host key-in used by MSet should be testable in the corresponding MicroStation/application command environment. MSet-specific macros/substitutions are the exception because they are processed before dispatch.

## Evidence boundary: unknown means unverified

> **Absence of authoritative evidence is not permission to infer syntax.**

When a requested action depends on host/application syntax, classify the available evidence before authoring or editing:

- **runtime-verified** - exercised successfully on the stated current host/environment,
- **runtime-observed** - behavior was observed, but the exact contract may still be narrower than a fully verified general rule,
- **historical/supporting evidence** - useful source evidence from older packages/manuals, not automatically current-host proof,
- **unverified** - plausible or requested behavior for which the exact command form is not yet established,
- **unsupported / known-bad** - explicitly outside the supported contract or known to fail.

Do not promote a historical example merely because its syntax looks familiar. If exact syntax is missing, preserve the gap, propose a small host-side runtime test, or simplify the design. In particular, local file/folder launch and configuration-variable expansion remain separately evidence-gated from the runtime-verified HTTP/HTTPS URL action documented in module 10.

## 10. Environment-specific dependencies are not syntax errors

A runtime-verified package can contain commands that depend on local configuration or additional applications.

The current `MSet_Polohopis` Starter candidate includes examples involving:

- `iNGs_Geo` commands,
- documentation-path variables,
- WMS configuration variables.

Do not replace such dependencies with guessed paths or invented commands merely to make the package look self-contained.

Instead:

1. identify the dependency,
2. preserve it when the user wants the same environment,
3. remove/replace/guard it only when that behavior is explicitly requested,
4. distinguish "XML/package valid" from "environment dependency available".

## 11. Four validation layers after an edit

A safe edit is not complete just because the text looks reasonable.

### Layer A - package integrity

Check that:

- all expected package files are present,
- relative paths still resolve,
- edited files retain intended encoding,
- the entry filename/Signum relationship is unchanged unless intentional.

### Layer B - XML/DTD/parser validity

Check that:

- XML is well-formed,
- external entities/DTD can be resolved,
- DTD validation succeeds when the package uses it,
- the instruction has its mandatory DTD (external package DTD or internal subset for a self-contained single file),
- root/required attributes/leaf structure are valid,
- `FormatVersion` is supported or intentionally legacy,
- `<Scales>` satisfies current parser rules.

### Layer C - MSet semantic transformation

For changed commands, evaluate the relevant behavior from modules 02 and 03:

- correct Group ancestry and Feature composition,
- separator normalization,
- `$C` / `$X`,
- `$S(...)`,
- automatic standard-scale substitutions,
- no accidental double scaling.

### Layer D - host/runtime behavior

When the change depends on Bentley/application key-ins or external resources, verify it in the intended host/environment when possible.

If runtime verification was not performed, say so explicitly. Do not turn "syntactically valid" into "runtime verified" by wording.

### Runtime evidence checkpoint - 2026-08-24

A new self-contained native instruction with `FormatVersion="2026.1"`, an **internal DTD subset**, nested Groups/Features and `<Scales>` was loaded by MSet `26.11.0.4` in MicroStation 2026. The MSet scale was then changed successfully. Treat this as runtime evidence for the package/DTD/scale acceptance of that tested instruction only. Individual host key-ins in the instruction were not thereby certified.

The same benchmark exposed a separate MSet ColorTuner UI crash while clicking the color wheel. It reproduced with the established `MSet_Polohopis` instruction and was therefore unrelated to the generated instruction content. Do not use that UI crash as evidence against instruction syntax or package validity.

## 12. Common error catalogue and recovery

### Error: malformed XML

Symptoms: parser cannot load the document, often after unbalanced tags, invalid attribute quoting, or broken entity syntax.

Recovery:

- compare against the pre-edit file,
- fix the smallest XML error first,
- do not simultaneously redesign unrelated structure.

### Error: missing or broken external entity/DTD/include

Symptoms: package loaded before a move/edit but no longer resolves an external resource.

Recovery:

- restore the original relative layout or deliberately update all affected references,
- verify the referenced file actually exists,
- do not flatten the package as a shortcut.

### Error: unsupported `FormatVersion`

Symptoms: explicit non-empty version is rejected by current MSet 2026.

Recovery:

- use `2026.1` for a deliberate native-format instruction,
- preserve missing version for legacy mode,
- never invent `2026.2`, `2027.1`, etc. without a published runtime contract.

### Error: required `Cpt` removed

Symptoms: Page/Group/Feature no longer satisfies current parser/format contract.

Recovery: restore a valid caption; do not invent a hidden technical ID as a substitute.

### Error: invalid `<Scales>`

Examples:

- multiple `<Scales>` elements,
- non-integer or non-positive values,
- non-positive `PrimaryScale`,
- `PrimaryScale` absent from the declared list.

Recovery: repair the declaration according to module 03, or remove `<Scales>` only when intentionally choosing the valid runtime default scale definition.

### Error: wrong node edited because captions repeat

Recovery: re-identify the node using Page/Group/Feature structural path plus nearby command context.

### Error: shared entity changed unintentionally

Recovery: inspect every reference to the changed entity. If only one use should change, restore the shared entity and introduce a deliberate local/source-specific change instead.

### Error: command inheritance changed by "cleanup"

Typical causes:

- moving a Group fragment into one Feature,
- moving Feature text upward into a Group,
- moving a lifecycle command into the inheritance tree,
- changing ancestor order.

Recovery: reconstruct the intended effective command from highest Group to Feature and restore the correct scope.

### Error: `$C` joins tokens incorrectly

Recovery: remember that `$C` removes the boundary separator but does not add whitespace. Restore the required authored whitespace.

### Error: unexpected prefix disappears after `$X`

Recovery: inspect every `$X` in the fully composed command. The last `$X` wins.

### Error: value is scaled twice

Recovery: check whether `$S(...)` was added around a value that is already covered by an automatic scale rule. Remove the redundant explicit scaling unless double scaling is intentional.

### Error: key-in is structurally valid but does nothing in the host

Recovery:

- do not rewrite XML blindly,
- verify the actual key-in in the target Bentley/application environment,
- check required external application/configuration/resources,
- classify the command as unverified if there is no authoritative evidence.

### Error: characters became corrupted after editing

Recovery:

- determine the original file encoding,
- restore bytes/declaration consistently,
- reapply only the intended semantic edit,
- validate the whole package again.

## 13. Minimal-change workflow for an LLM

For a user-requested modification, follow this sequence:

1. load all four required Instruction Author modules,
2. inspect the complete relevant package,
3. identify the exact target by structural path and real source file,
4. record invariants that must remain unchanged (entry name, encoding, references, FormatVersion, unrelated commands),
5. make the smallest requested semantic change,
6. validate package/XML/parser structure,
7. reason through command composition/substitution if command behavior changed,
8. verify host/environment behavior when required and available,
9. report changed files and any unverified runtime assumptions.

Do not combine a requested functional change with unrelated beautification, mass reformatting, encoding migration, renaming, DTD redesign, or legacy-format migration unless the user explicitly requested those changes.

## 14. What `readyForFullAuthoring` means

After modules 01-04, the 64-bit Instruction Author track may advertise:

```text
readyForFullAuthoring = true
```

This means the model has the complete **core MSet instruction/package authoring contract currently published for MSet 2026 standard mode** and may safely create, review, or modify instructions when it respects the evidence rules below.

It does **not** mean:

- every Bentley/OpenRail/OpenRoads/OpenSite key-in is known,
- every external application command is known,
- Annotation Scale is covered,
- historical `$M(...)` control macros are supported,
- an untested host/environment command may be claimed runtime-verified.

Unknown key-ins or environment-specific behavior remain evidence-gated even when the Instruction Author track itself is complete.

## Completion check

Before claiming Instruction Author readiness, the model should be able to answer all of these correctly:

1. Must it inspect the complete package before editing? **Yes.**
2. May it silently convert CP1250/XML encoding to UTF-8? **No.**
3. May it rename the entry XML as cosmetic cleanup? **No; that changes Signum.**
4. Should it automatically add `FormatVersion="2026.1"` to a legacy instruction during unrelated cleanup? **No.**
5. Is missing `<Scales>` an error? **No.**
6. Are repeated `Cpt` captions invalid? **No.**
7. May an empty Feature command be valid? **Yes.**
8. May it edit a shared entity without checking other references? **No.**
9. Does valid XML prove an external Bentley/application key-in works? **No.**
10. What are the four validation layers? **Package integrity; XML/DTD/parser; MSet semantic transformation; host/runtime behavior.**
11. May it claim runtime verification if no runtime test was performed? **No.**
12. Does `readyForFullAuthoring=true` remove the Annotation Scale / `$M(...)` / unknown-key-in boundaries? **No.**
