Files
llm/docs/1c-adapter-api-contract.md

3404 lines
142 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 1C Adapter API Contract
## Configuration repository control
The adapter is SQL-only. It does not start, automate, emulate, or require
Designer/Configurator. Configurator actions are performed by a human and are
outside the adapter's execution boundary.
Repository operations are available through `repository.status`,
`repository.lock.plan`, `repository.lock`, `repository.lock.confirm`, `repository.lock.verify`,
`repository.unlock`, `repository.commit.plan`, and `repository.commit`.
Configuration is selected only by `payload.base_id`. No Designer executable,
Configurator endpoint, bridge, or external 1C runner is used by this adapter.
`repository.lock_mode=manual` is selected per base. Manual mode requires no
Designer integration:
`repository.lock.plan` returns the exact public development-object names to
lock in Configurator, and `repository.lock.confirm` records the user's explicit
confirmation for only that object set. Such a session is marked
`user_confirmation_only`; `repository.lock.verify` returns
`manual_confirmation_unverified` and never represents it as an automatic
repository check.
In the SQL-only release, `repository.lock.request` persists an adapter-side
coordination request with status `pending_user_lock` and the resolved public
object scope. It deliberately does not write a marker into the 1C infobase SQL
database: such a marker would not create a native repository lock.
`repository.lock.request.status` exposes the request state, and
`repository.lock.confirm` can consume its `request_id`; confirmation always
uses the immutable object set stored in the request.
Manual requests expire after `ONEC_REPOSITORY_REQUEST_TTL_SECONDS` (24 hours
by default) and may be explicitly cancelled with
`repository.lock.request.cancel`. Manual confirmations expire after
`ONEC_REPOSITORY_CONFIRMATION_TTL_SECONDS` (2 hours by default). After the user
releases the objects in Configurator, `repository.lock.close` closes the
confirmation, marks its originating request as `closed`, and immediately blocks
further SQL writes through that session.
The adapter keeps a bounded audit trail of request creation, confirmation,
cancellation, and closure and exposes it to the administrative requests view.
Repository coordination records only the human-confirmed scope. It does not
invoke Designer repository commands and does not prove a native lock. For
configured bases, saved-state apply is blocked until the caller supplies an
active adapter-owned `lock_session_id`; that session is coordination evidence,
not a native repository transaction.
Status: draft, read-only first.
Related work plan: `docs/1c-extension-layer-plan.md`.
## Source Boundaries
- The live adapter works with 1C through SQL storage only.
- XML exports and Form.xml files may be used by this project for analysis,
fixtures, learning, diffing, and rule discovery, but they are not a live 1C
write transport for the adapter.
- When XML-derived rules are promoted into the adapter, the runtime write path
must still resolve to concrete SQL storage targets such as `ConfigSave` or
`ConfigCASSave`, with explicit gates and readback verification.
- SQL readback is not proof that Configurator accepts, displays, saves, or
activates a change. Only a human may provide that confirmation.
- The adapter must reject, rather than fabricate, a `ConfigSave`/
`ConfigCASSave` container or signature whose SQL protocol is not proven.
## Data Composition Schema Query Writes
`scd.patch` changes only one proven direct XML scalar: a dataset `query`, a
calculated-field `expression`, or a resource `expression`. It resolves the
report and SCD by public 1C names, preserves the surrounding SQL payload bytes
and compression envelope, and never accepts a storage key from a caller.
For `execution_mode=apply`, `apply_and_verify`, or `apply_and_rollback`, a
missing saved SCD payload is prepared internally through the established
saved-state copy codec when `allow_sql_saved_state_prepare=true` is supplied.
The caller still explicitly authorizes the eventual edit with
`allow_saved_state_write=true` and `allow_sql_saved_state_apply=true`.
`apply_and_rollback` additionally requires
`allow_sql_saved_state_rollback=true`. It restores the exact apply backup, not
a newly encoded copy of the old query. If this request created the saved-state
overlay, it then removes only receipt-recorded rows after hash precondition
checks. A successful result proves SQL readback and cleanup only; it does not
prove Configurator visibility, acceptance, or activation.
## Report And Appearance Inspection
`report.inspect` is the read-only entry point for a report component graph.
It accepts a public report name and returns only independently confirmed
modules, forms, templates and SCD components. A form called
`ОсновнаяСхемаКомпоновкиДанных` remains a form; it is never promoted to an SCD
from its name or a guessed `.0` stream.
```json
{"method":"report.inspect","payload":{"base_id":"upo_test","report":"ФинансовыйРезультат"}}
```
`appearance.inspect` is a separate read-only reader for a base
`CommonTemplate` whose `.0` carrier has the `AppearanceTemplate` XML root.
This selects the payload reader only; it does not establish the 1C platform
`TemplateType`, which remains unresolved until its metadata descriptor is
decoded.
It returns raw XML-backed `item(parameter, value)` rules and an XML tag
outline. It has no write operation, and an extension template returns explicit
`unsupported` until an extension carrier route is proven.
```json
{"method":"appearance.inspect","payload":{"base_id":"upo_test","template":"ОформлениеОтчетовБежевый"}}
```
## User Identity And Access Terminology
An unqualified user request means an **infobase user**: the platform identity
visible in Configurator under administration of infobase users. It does not
mean the BSP `Catalog.Пользователи` record.
The two layers are intentionally separate:
| Layer | Canonical term | Source | Authoritative for |
|---|---|---|---|
| Platform | `infobase_user` / Configurator user | `dbo.v8users` and the 1C `ПользователиИнформационнойБазы` runtime API | login identity, authentication flags, platform administrator flag, assigned platform role set and exact platform roles |
| Application | `bsp_catalog_user` / BSP user | BSP catalogs, access groups, profiles and access registers | BSP membership, profiles, access groups, RLS/access-key chains and application access diagnostics |
Routing rules:
- ordinary "users", "user roles", "login", "password", and "Configurator
users" start with `infobase.users.search` or `infobase.user.get`;
- explicit BSP/group/profile/RLS questions use `access.users.search` and
`access.user.explain`;
- a name match between the layers is correlation only and never proves that
the records are identical;
- BSP groups/profiles must never be reported as the exact role assignment of a
Configurator user;
- SQL `RolesID` proves the assigned platform role-set identity, but exact role
names require the supported 1C runtime `ПользователиИнформационнойБазы` API.
`infobase.users.search` and `infobase.user.get` expose only safe `v8users`
fields: platform id, name/full name, change time, login-list visibility,
authentication-presence flags, administrator flag, `RolesID`, and protected
payload size. They never expose `Data`, password hashes, password-policy blobs,
material keys, or raw `users.usr` content. Until a runtime connector is added,
responses set `role_assignment.exact_role_names_status=runtime_required`.
### Configurator User Password Operations
Password mutation is available only for the platform `infobase_user` layer:
- `infobase.user.password.capabilities` reports whether the protected path is
ready for a concrete `base_id`;
- `infobase.user.password.status` reports `empty`, `set`, or
`standard_authentication_disabled` for one exact platform user. It never
returns password hashes or `Data`;
- `infobase.user.password.set` changes the password and requires `user`, the
exact 32-hex `confirm_user_id`, `new_password`, and
`allow_password_change=true`. It uses the same guarded SQL transaction as
`clear`, storing the Base64-encoded SHA-1 pairs for the UTF-8 password and
its Unicode uppercase form;
- `infobase.user.password.clear` removes the password and requires `user`, the
exact 32-hex `confirm_user_id`, and `allow_password_clear=true`; it rejects a
`new_password` field. This operation uses SQL only: it locks the exact
`dbo.v8users` row, decodes that row's XOR-protected `Data` container, replaces
only the first adjacent current SHA-1/Base64 password pair with the empty
password pair, writes with an old-`Data` concurrency predicate, and verifies
readback before commit;
- a platform administrator additionally requires
`allow_administrator_password_change=true`;
- normally both mutations are blocked when `ONEC_ADAPTER_SERVICE_TOKEN` is
empty. A disposable isolated test stand may explicitly set
`ONEC_INFOBASE_USER_ADMIN_ALLOW_UNAUTHENTICATED=true`; it affects only this
isolated SQL operation and must never be enabled in production.
Both operations select the exact user through `infobase.user.get` and update
only `dbo.v8users.Data`. The clear-text password for `set` exists only in memory
and is not included in responses or write-history payloads. Neither operation
updates `Params/users.usr`, `EAuth`, roles, administrator flags, names, or BSP
records. Both are rejected when `EAuth=0`, because changing stored hashes does
not enable standard authentication.
The SQL path decodes the row-specific XOR key, patches the first adjacent
current-hash pair in the authentication section, reuses the original key and
byte layout, and verifies that no other parsed scalar changed. A compare-old
`Data` predicate prevents overwriting a concurrent user edit.
Successful `set` and `clear` results are recorded in
`metadata.write.history` with method, operation, target platform id/name,
transport, status, and verification result. Request payloads are never written
to that history, so `new_password` is not persisted. The SQL layout with 43
root fields was live-verified on `upo` during an administrator password clear.
## Undecoded Evidence
Public decode/read methods should not drop useful payload evidence when a
decoder is incomplete or when only part of the object is understood. Methods
that expose decoded object, part, form, or template payloads accept:
```json
{
"evidence_mode": "none | summary | full | raw"
}
```
Contract:
- `none`: omit `undecoded_evidence`;
- `summary`: return compact role, markers, root signature, string samples,
payload size/hash metadata, and safe stream/base64 samples;
- `full`: return broader samples and longer text excerpts for agent-side
analysis;
- `raw`: return the broadest evidence. Low-level storage offsets, block hashes,
and physical coordinates are exposed only together with
`include_storage=true`.
`evidence_mode` is intentionally separate from object `view`
(`effective/base/extension`): `view` selects the metadata layer, while
`evidence_mode` selects diagnostic detail.
Current methods using this contract include `metadata.object.decode`,
`metadata.object.parts`, `metadata.object.templates`,
`metadata.object.template.details`, `metadata.form.decode`, and
`metadata.object.full` through its `parts_summary` section.
## Template Content Export
`templates.read` can return the actual current SQL-stored template content in
read-only mode. Content is opt-in and bounded:
```json
{
"base_id": "upo_test",
"kind": "Document",
"name": "АктВыполненныхРабот",
"template": "ПФ_MXL_УдалитьАкт",
"view": "full",
"include_content": true,
"max_content_bytes": 262144
}
```
Each part then contains `content_export.container`: media type, decoded byte
size, returned byte size, SHA1, truncation flag, and base64 data. Embedded
decodable stream/base64 blocks are also returned in `extracted_text`, including
HTML as text. `max_content_bytes` is limited to 1 MiB per returned item. The
operation never writes to 1C SQL tables; it only reads the configured database
and does not perform platform rendering to pixels or PDF.
## Managed Form Element Types
SQL form profiles distinguish every element type observed in the reference UPO
`Form.xml` export. This includes containers, pages, command bars, tables and
their search additions, input/label fields, checkbox fields, picture fields,
radio-button fields, spreadsheet-document fields, label/picture decorations,
context menus, and extended tooltips. XML is used only to confirm decoding
rules; live `metadata.form.decode` and `metadata.object.form.details` responses
are produced from SQL payloads. Dynamic table profiles also expose confirmed
read-only/skip-on-input and row-set-change flags, height in table rows, footer,
row-selection mode, horizontal/vertical line flags, alternating-row color,
automatic row insertion, and drag-start/drag flags. The dynamic-table SQL
positions for `ChangeRowSet`, `HeightInTableRows`, and `Footer` were confirmed
against four distinct tables in the reference UPO form. Rare layout and
behavior properties remain best-effort until their SQL positions are confirmed
by multiple samples.
The complete offline UPO inventory covers 6,748 `Form.xml` files, all parsed
successfully, with 821,077 named elements, 41 element kinds, and 253 direct
property tags. Runtime still does not read XML. SQL section records additionally
decode `CurrentRowUse` and `ModifiesSavedData` for commands and `MainAttribute`
and `SavedData` for attributes. The confirmed payload positions are 9/10 for
command current-row/saved-data behavior and 10/11 for attribute main/saved-data
flags. Table search, view-status, and search-control additions expose a
structured `AdditionSource` derived from their decoded parent-table hierarchy.
Its public value contains `owner_element` and `representation`; it deliberately
does not use the reserved `table` key, which denotes physical SQL storage in
adapter diagnostics. Command-bar buttons also decode `ButtonImportance`,
`GroupHorizontalAlign`, and `GroupVerticalAlign`; label/picture decorations
decode both group-alignment properties. Input, label, picture, checkbox,
radio-button, and chart fields use positions 53/54. Marker-22 containers
(ordinary/column groups, command bars, and pages) use the last three and last
two entries of their variable-length node (`-3/-2`). The other confirmed SQL
positions are 11/41/42 for command-bar buttons and 32/33 for decorations. The
vertical enum is normalized as `Top`, `Center`, `Bottom`, or `Auto`. These
positions were cross-checked against contrasting XML declarations and the
matching live SQL payloads; XML remains an offline analysis source only.
Marker-35/37 fields also expose `AutoEditMode=true` when position 26 is
`EnterOnInput`. In the reference document-form inventory, all 11,817 explicit
`AutoEditMode` declarations are paired with `EditMode=EnterOnInput`; the live
SQL payload stores that pair as the single enum code `2` at position 26. The
adapter therefore returns `AutoEditMode` as a confirmed derived property and
does not invent a separate storage position.
Table additions have two confirmed live SQL layouts: marker-5 records embedded
directly in the variable tail of a dynamic list/table, and the same records
embedded in its auto command bar. Both are normalized to public marker-6
addition items. Validation against 12 UPO forms decoded 39/39 XML-declared
search-string, view-status, and search-control additions with a resolved owner
and representation.
The variable-length dynamic-table tail is decoded relative to the end of the
element after validating the four table-addition records. It exposes
`SearchStringLocation`, `ViewStatusLocation`, `SearchControlLocation`, and
`FileDragMode`. The location enum maps were confirmed against eleven live SQL
tables covering `Default`, `None`, `CommandBar`, `Top`, `FormCaption`, and
`PullFromTop` values present in the reference XML export.
Related-form discovery follows the object descriptor layout for reports
(`Form` section 5), data processors (section 6), exchange plans (section 6),
selection criteria (section 3), and settings storages (section 4). Report and
data-processor template sections are kept separate from forms.
Live descriptor routes are also confirmed for enum forms (section 3),
information-register forms (section 5), accumulation-register forms (section
8), business-process and task forms (section 4), chart-of-characteristic-types
and chart-of-calculation-types forms (section 7), chart-of-accounts forms
(section 6), and document-journal forms (section 6). Form list and full SQL
payload decoding were verified by public object/form names for every listed
kind. Template sections for exchange plans and charts of characteristic types
remain distinct at section 4.
Template discovery additionally covers enum templates (section 4),
information-register templates (section 6), and document-journal templates
(section 3). Catalog templates use section 3; section 4 is the catalog command
section. Safe bounded `templates.read include_content=true` export was verified
for the newly routed kinds, including MOXCEL content.
Object-command discovery is confirmed for catalogs (section 4), documents
(section 6), data processors and document journals (section 5), accumulation
registers (section 4), information registers and tasks (section 8), and
exchange plans and reports (section 7). When a separate command descriptor is
absent, the public command identity falls back to the identity embedded in the
owner descriptor. Results are deduplicated by command GUID/name.
## Payload Diff
`payload.diff` is a diagnostic method for comparing two payload snapshots. It
accepts `before` and `after` sources as either live storage pointers
(`base_id`, `table`, `file_name`) or inline payloads (`payload_base64`,
`payload_hex`, or `text`). It requires `diagnostic=true`.
The response includes:
- byte sizes and SHA1 hashes;
- decoded envelope metadata;
- unified text diff;
- scalar brace-tree changes with paths such as `$.1.3.2`;
- changed string sequence entries;
- compact `undecoded_evidence` for both sides when `include_evidence=true`.
Use it after manual Designer/configurator edits to identify which raw payload
nodes changed before promoting a rule into a higher-level decoder or writer.
## Agent-Facing Addressing
Agent-facing selectors and answers should prefer full semantic 1C paths over
GUIDs, SQL names, CAS keys, or bare local names.
Default path shape:
```text
<ObjectKind>.<ObjectName>[.<Section>.<Member>...]
```
Examples:
```text
Справочник.Контрагенты
Справочник.Контрагенты.Наименование
Документ.РеализацияТоваровУслуг.Товары.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Ресурсы.Цена
Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Товары
ОбщийМодуль.ИнтеграцияСCRM.ОтправитьКонтрагента
```
Short names are allowed as input conveniences, but adapter methods must either
normalize them to one `canonical_path` or return ambiguity candidates. Bare
member names such as `Наименование` are not safe write targets without object,
form, module, or routine context.
Metadata path resolution and BSL symbol resolution are separate operations. A
code expression such as `Номенклатура.ЕдИзмерения.Код` starts from a local
symbol until the adapter proves that the symbol maps to a metadata path or
typed value.
Resolved agent-facing objects should include, where known:
- `canonical_path`;
- `context_path` when a short path was resolved inside a known context;
- `path_kind`, for example `metadata_object`, `metadata_member`,
`form_element`, `module`, `routine`, or `code_symbol`;
- `presentation` and synonym;
- `ref` and GUID/storage evidence for internal follow-up calls.
## BSL Symbol Resolution
Command:
```text
python scripts/resolve_1c_bsl_symbol.py
--metadata <metadata snapshot>
--modules <bsl module snapshot>
--expression <BSL expression>
--module-id <module-id>
[--object-kind <Kind>]
[--object-name <Name>]
[--routine-name <Routine>]
```
Safe Unicode command shape:
```text
python scripts/resolve_1c_bsl_symbol.py
--metadata <metadata snapshot>
--modules <bsl module snapshot>
--expression-b64 <utf8-base64 BSL expression>
```
Output schema:
```text
onec_bsl_symbol_resolution.v1
```
Live adapter RPC:
```json
{
"method": "code.symbol.resolve",
"payload": {
"base_id": "<base-id>",
"expression": "Номенклатура.ЕдИзмерение.Код",
"module_ref": "<module-ref-from-code-search>",
"routine_name": "<routine-name>"
}
}
```
Purpose:
- resolve BSL expressions inside a concrete module/routine/form context before
treating them as metadata paths;
- return `metadata_path` only for full semantic paths such as
`Справочник.Номенклатура.Артикул` or for members proven by context, for
example a current object-module standard attribute;
- in live adapter mode, read the module through `modules.read`, use
`metadata.definition.find` for full metadata paths, and use
`metadata.object.attributes` for context-proven owner members;
- return `parameter` or `local_variable` when the first expression segment is
declared in the current routine/module, with `safe_as_metadata_path=false`;
- return unresolved candidates for short object names such as
`Номенклатура.ЕдИзмерение.Код` instead of silently converting them to
`Справочник.Номенклатура...`.
## Agent-Facing Code Writes
Normal coding agents should write BSL through `code.write`, not through SQL,
storage rows, payload paths, or `metadata.module.write_apply`.
### Working-state and saved-state ownership rule
An agent works only with the effective working configuration. It reads the
saved development version when one exists and otherwise reads active code; it
does not determine whether `ConfigSave` or `ConfigCASSave` exists, and it must
not call a separate saved-state preparation operation as part of a normal code
change.
The adapter owns that transition. A `concrete_reference` returned by
`code.search` or `code.read` is an opaque proof of the exact active module
stream, extension, and layer—not permission to write active storage. After
preflight has resolved that reference, a normal apply must do the following
inside the adapter:
`code.write` accepts the same reference either directly or inside
`write_selector.target`. It verifies the supplied public `ref`, extension,
layer, canonical path, and routine against that exact stream, then routes it
to the saved copy without repeating `metadata.object.modules` discovery.
For one apply request the adapter authorizes the public extension scope once
before preparation. Its internal prepare and writer stages reuse that
process-bound authorization; they must not repeat broad support/owner scans
against `ConfigCASSave`. If authorization is absent, the request returns a
bounded `blocked` result before any support scan or saved-state mutation.
For a client transport deadline shorter than the adapter write budget, call
`adapter.job.start` with `method="code.write"` and the same public payload,
then poll `adapter.job.get`. This preserves the final structured write result;
the caller must not retry the SQL write while the job is running.
1. verify the exact extension/layer and active source stream;
2. create a missing saved-state copy through the proven
`Config`/`ConfigCAS` to `ConfigSave`/`ConfigCASSave` copy path;
3. apply the guarded edit only to saved state;
4. make a backup, validate BSL and the old-text/SHA preconditions, and reread
the written result; and
5. support the requested rollback, including removal or restoration of any
adapter-created saved-state copy.
`metadata.write.preflight` reports such a first write as `status=ready` with
`route.preparation.status=adapter_managed`,
`route.preparation.caller_action_required=false`, and
`saved_state.status=will_prepare`. `needs_prepare` is reserved for a route
whose copy protocol is not sufficiently proven for the adapter to execute.
The adapter must never write the active `Config` or `ConfigCAS` layer.
For a hash-keyed extension overlay, this internal copy includes the live
extension root manifest (`root_cas_key`) and the confirmed object parts. An
exact BSL stream reference remains the write target, but must not reduce the
saved-state preparation to that leaf stream alone.
The caller never invokes or waits for this preparation as a separate workflow:
`code.write` performs the bounded copy, write, verification, and readback as
one adapter operation. Its preparation gate is restricted to the confirmed
extension layer and public object; it does not perform a whole-extension
support scan before copying proven source parts.
`code.write` accepts 1C names and code text:
```json
{
"method": "code.write",
"payload": {
"base_id": "upo_test",
"object_type": "CommonForm",
"object_name": "t_Форма",
"routine_name": "ЗаменаДомена",
"routine_text": "Процедура ЗаменаДомена(Команда)\n\t// code\nКонецПроцедуры\n"
}
}
```
Contract:
- default `mode` is `plan` and does not write SQL. `apply`,
`apply_and_verify`, and `apply_and_rollback` must be requested explicitly;
they save only to the working `ConfigSave`/`ConfigCASSave` layer, not to
production;
- every `code.write` response includes `write_mode.target=saved_state`,
`write_mode.activation_state=not_activated`, and
`write_mode.production_apply=false`;
- the normal agent view is the effective working configuration: a matching
`ConfigSave`/`ConfigCASSave` overlay is read ahead of active code. Agents
do not inspect, create, or select saved-state rows. For a first extension
write, the adapter takes the exact active module handle returned by
`code.search`/`code.read`, creates the proven `ConfigCASSave` copy inside
its guarded apply workflow, and then edits that copy. Preflight reports this
as `route.preparation.status=adapter_managed`; no separate prepare call is
required from the agent.
- saved-state `code.read` and `code.search` responses include
`current_state.source=saved_state` and
`current_state.activation_state=not_activated`;
- `code.read state=working` is save-first with active fallback,
`state=save` reads only the saved layer, and `state=active` skips saved-state
lookup. `state=both` returns side-by-side layers and comparison metadata;
- SQL/storage gates are set by the adapter for this facade;
- public responses hide physical storage details unless
`include_storage=true`;
- full module replacement uses `module_text`, `full_text`, or `code`;
- routine replacement uses `routine_name` plus `routine_text`;
- fragment replacement uses `old` plus `new`. With `routine_name` or a
routine-level `canonical_path`, `old` must occur exactly once inside that
procedure/function; without routine scope, it must occur exactly once in the
current saved module text;
- if the fragment is missing or repeated, the adapter returns
`fragment_not_found` or `ambiguous_fragment` and does not write;
- low-level storage methods remain diagnostic and implementation details.
For embedded form modules the adapter writes only the scalar module token in
the saved form payload with `path_preserve_format`. Whole-form payload
canonicalization is forbidden because Designer may reject the form even if the
payload decoder can parse it. A write plan for such a container returns a ready
`code.write` apply hint rather than asking the caller to invent a
`#stream:<index>`.
## Resolve Object
Command:
```text
python scripts/resolve_1c_object.py
--kind <ConfiguratorKind>
--name <ConfiguratorName>
--index <unified object route index>
```
Output schema:
```text
onec_object_resolution.v1
```
Purpose:
- resolve objects by configurator-visible names, synonyms, qualified names, and
generated type names such as `DocumentRef.ПриходнаяНакладная`;
- return the canonical base object plus extension overlays;
- keep storage details under `storage`, so agent-facing code can continue to
operate with 1C metadata names.
## Object Brief Context
Command:
```text
python scripts/get_1c_object_brief_context.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--view effective|base|extension
--extension <ExtensionName>
--max-attributes <N>
--max-modules <N>
--max-forms <N>
--output <json>
```
Output schema:
```text
onec_object_brief_context.v1
```
Purpose:
- provide the default starting context for an agent after a user names a 1C
object;
- keep the response compact: object identity, active extension names,
attribute summary, tabular section names, form list, module list, overlay
counts, and suggested follow-up tools;
- use `view=effective` by default so the agent sees the same working object
picture as the user sees in Configurator;
- avoid loading large BSL modules or full form XML; use the dedicated module
and form APIs for detail reads.
## Fact Resolution
Command:
```text
python scripts/resolve_1c_fact.py
--index <unified object route index>
--path <Kind.Name.Member>
--view effective|base|extension
[--extension <ExtensionName>]
```
Safe Unicode command shape for agents and PowerShell callers:
```text
python scripts/resolve_1c_fact.py
--index <unified object route index>
--path-b64 <utf8-base64 Kind.Name.Member>
```
Output schema:
```text
onec_fact_resolution.v1
```
Purpose:
- verify concrete facts about the current configuration before code generation,
for example `Справочник.Номенклатура.Цвет` or
`Документ.ПриходнаяНакладная.ДатаСоздания`;
- return `exists`, `confidence`, `area`, object identity, matched member, and
source provenance;
- support object, attribute, tabular section, form, module, and snapshot-backed
checks through the same agent-facing shape;
- keep examples and old snapshots out of the current-configuration path unless
the caller explicitly passes `--snapshot`.
- normalize positive results to a full `canonical_path` and return ambiguity
candidates when a short path is not unique.
Policy:
- RAG may explain platform behavior, patterns, and documentation.
- `resolve_1c_fact.py` or a richer adapter method must confirm concrete object,
attribute, form, command, module, and data facts for the selected base.
- A negative result means the fact is not confirmed in the provided source; the
agent should not silently replace it with a fact from examples or generic
documentation.
## Live Adapter Navigation
The REST adapter exposes metadata and BSL navigation through public selectors.
Agents should prefer these selectors over diagnostic storage fields.
Object selectors:
- Object-scoped methods accept the same public selector shapes: `ref`,
`kind` + `name`, `guid`, or MCP-friendly aliases `object_type`,
`object_name`, and `object_guid`.
- `ref` can be a public qualified object reference such as
`Обработка.<Name>` or `Document.<Name>`; the adapter normalizes Russian and
English metadata kind names to the canonical internal kind.
- Public selectors returned by the adapter keep backward-compatible
`kind`/`name`/`guid` fields and, when `kind` + `name` are known, also include
compact `ref=<canonical-kind>.<metadata-object-name>`.
- Do not branch on concrete object names in client or MCP code. Normalize the
selector once and pass the resulting public selector through adapter methods.
- If a result contains `read_selector.method`, call that method with the
selector payload as-is. Do not reconstruct the selector from display text or
storage diagnostics.
- `help.methods` exposes `selector_capabilities` for object-scoped methods.
Agents should use these flags instead of inferring selector behavior only from
natural-language descriptions.
Important methods:
- `data.schema`, `data.list`, `data.get`, `data.count`, and `data.query` expose
logical 1C data names while reading physical SQL tables. The object is
selected by public `ref` (for example `Catalog.<Name>`) or by
`kind` + `name`; a row is selected separately with `record_ref`. SQL table
names and `_Fld...` columns are internal routes, not caller-facing selectors.
Constants are exposed as a typed `value`; enumeration rows include their
public value `name`, `synonym`, and `value_ref`. Business-process storage is
resolved through the platform `_BPr<N>` route internally.
- `additional_attributes.find` is the read-only entry point for additional
requisites. It reads a public `ChartOfCharacteristicTypes` selector (by
default `ДополнительныеРеквизитыИСведения`) and accepts `query` for a
description search. Its `empty_source` result is deliberately distinct from
`not_found`: it means that the resolved chart route has no records in the
selected infobase, so no property reference or value type can be claimed.
`additional_attributes.storage.resolve` requires a confirmed 32-hex
`property_ref` plus `owner_ref`. It searches candidate information registers
and returns a storage join only after live metadata proves dimensions
`Объект` and `Свойство`, a `Значение` resource, and that `Свойство` is a
reference to the selected PВХ. Otherwise it returns `unresolved` and never
guesses physical `_Fld...` columns.
For `ChartOfCharacteristicTypes`, `data.schema` and the find result also
expose chart-level `allowed_value_types` with its live Config evidence path.
This is explicitly not represented as the type of an individual property
record until that record's `ТипЗначения` route is decoded.
- `data.present` returns a compact presentation for one `record_ref`, and
`data.movements` reads register rows for a `recorder_ref`.
- BSP access-key methods use the same object/record separation without
overloading their query-area selector. For `access.keys.query`,
`kind=object` selects the access-key area; it is not a metadata kind. Pass
`object_ref=Справочники.Номенклатура` to select the metadata object and
`record_ref=<32-hex-ref>` to select one application-data record.
`access.object_keys.resolve` and `access.object.explain` accept the same
pair. The adapter resolves `object_sql_number` and `object_id` internally.
Raw `object`, `object_id`, and `object_sql_number` remain compatibility
filters only and should not be generated by new MCP clients.
- `metadata.adapter.audit include_unmapped=true` distinguishes configuration
metadata from platform storage. Live `upo_test` DBNames verification showed
the former candidate roles `Acoustic`, `Bots`, `Ecs`, `LangModel`,
`MobileClientDataExchange`, `STT*`, `URLExternalData`, and
`WebSocketClients` as singleton platform-system tables, normally carrying
the zero GUID. `ExtDataSrcPrms` is auxiliary external-data-source storage.
None of these roles is exposed as an invented public metadata kind.
- `metadata.object.form.details` decodes form commands with their explicit
`Action` value from the SQL form payload. `command_links` resolve that action
against the complete form-module routine index; `routines_sample` is only a
compact preview and never limits handler resolution.
- The same form details expose command `CurrentRowUse`/`ModifiesSavedData`,
attribute `MainAttribute`/`SavedData`, and structured table-addition
`AdditionSource` properties directly from the live SQL payload. Command-bar
buttons additionally expose `ButtonImportance`, `GroupHorizontalAlign`, and
`GroupVerticalAlign`; decorations expose their horizontal and vertical group
alignment.
- `metadata.object.special.details` for `ScheduledJob` returns the complete
decoded SQL schedule: date/time windows, completion interval, intraday
repeat and pause, weekdays, day/month restrictions, months, and week/day
repeat periods, together with use/predefined and restart settings. It also
resolves the handler's common module and returns `handler.read_selector`;
pass that selector unchanged to `modules.read` to read the exact procedure.
A non-predefined disabled job may legitimately return
`schedule.status=not_configured` when its separate `.0` schedule payload is
absent.
- `metadata.object.properties` has kind-specific live SQL decoders for
`EventSubscription`, `WebService`, and `HTTPService`. Event subscriptions
expose their source objects, event and handler. The handler contains a
`read_selector` that can be passed unchanged to `modules.read` to obtain the
exact common-module procedure from the working SQL state. Web services expose namespace,
XDTO packages, descriptor/session settings, operations and parameters; HTTP
services expose root URL/session settings, URL templates, HTTP methods and
handlers. XML exports are used only to establish and test the Config layout,
never as a runtime data source.
- The same property API has SQL decoders for `CommonAttribute`,
`SessionParameter`, `FunctionalOption`, and `FunctionalOptionsParameter`.
Common attributes expose their value type, content objects, indexing,
full-text/history flags, and data-separation settings and references.
Session parameters preserve composite types, including unions of several
reference or platform types. Functional options expose their storage
location, privileged-get flag, and every affected top-level or nested
metadata object; functional-option parameters expose every `Use` target.
XML exports are used only to learn field layout and verify names—the runtime
values and references always come from the selected SQL base.
- `CommonCommand`, `SettingsStorage`, and `Subsystem` also have dedicated
SQL-only property decoders. Common commands expose their public command
group (including standard platform groups), parameter type, and a ready
command-module read selector. Settings storages expose all four default and
auxiliary save/load form roles plus every owned form; every physical module
stream is classified as a manager module. Subsystems expose use/help/command
interface flags, picture, content, child subsystems, and references decoded
from the separate command-interface SQL part.
- A normal `metadata.objects.list` request validates a kind-specific cache hit
against the current configuration-root object count. If a root-discovered
kind is only partially represented in the local metadata cache, the adapter
ignores that cache hit and returns the authoritative live SQL list. This
prevents a partial `DBNames` cache from hiding root-only objects such as
settings storages. The check and fallback are read-only for the 1C database.
- `Language`, `CommonPicture`, `Style`, and `StyleItem` are decoded from live
SQL as first-class metadata. Languages expose their language code. Common
pictures expose choice/appearance flags and a bounded binary summary from
their `.0` part (format, byte count, and hash) without returning unbounded
binary data. Recognized formats include PNG, JPEG, GIF, BMP, ICO, SVG, and
zipped 1C picture packages. Styles expose every value from the separate
style table; style items decode absolute/web/standard colors, font
attributes, and borders. Unknown platform codes remain explicit with
`status=unknown_code`.
- `XDTOPackage` reads its live `.0` XML payload and returns namespace/form
settings, imports, object/value types, nested anonymous type definitions,
properties, constraints, and enumeration values. `WSReference` reads the
location and generated manager identifiers from its main payload, then
decodes the `.0` stream container into WSDL and XSD. The public result links
messages, port-type operations, SOAP actions, bindings, services, ports,
addresses, schemas, types, elements, restrictions, and enumerations. XML
files exported by Configurator are not used at runtime.
- `ExternalDataSource` is decoded from the live SQL `Config` hierarchy. The
source returns its tables, cubes, and functions; each table has a public
name-based ref, its `NameInDataSource`, key fields, and the complete field
collection with SQL name, 1C value type, `ReadOnly`, and `AllowNull`.
Primitive number, string, date, boolean, and binary (`R`) patterns are
decoded without consulting the Configurator export. Child payloads are read
in one batch. The adapter only describes connection metadata and never opens
or changes the external system itself. Live `upo_test` validation decoded
30 tables, 733/733 typed fields, and 53 key-field links; this base contains
no cubes or functions.
- A top-level `CommonTemplate.<Name>` is a direct template selector for
`metadata.object.template.details`, `templates.read`, `templates.analyze`,
and `templates.map`. It is resolved internally to the Config GUID and its
payload parts, while the public response preserves the `CommonTemplate`
name and ref. This is distinct from a template nested under another metadata
object and no longer returns an empty template collection.
- `DefinedType.<Name>` is decoded completely from its live SQL `Config`
payload. `metadata.object.special.details` returns the identity, comment,
union value type, and every constituent type. Generated platform types are
resolved internally to their owning metadata object, including business
process object/ref/selection/list/route-point variants and constant value
managers. A full `upo_test` audit read all 612 payloads and resolved all
1,943 unique type GUIDs across 6,241 type references; no unresolved type
remained.
- `SelectionCriterion.<Name>` returns its value type, standard-command flag,
default forms, list presentation, and complete metadata content collection.
Content GUIDs are translated to public name-based refs. Live validation
decoded all 11 criteria and resolved 862/862 content references.
- `Enum.<Name>` returns its identity, comment, standard-command and quick-choice
settings, choice mode, and ordered values with public refs. Multilingual and
empty-synonym identities are supported. Live validation decoded 1,226 enums
and 9,380/9,380 values.
- `metadata.object.modules`, `modules.read`, and `code.read` support
`WebService`, `HTTPService`, and `IntegrationService`. Service Config parts
can contain both the complete BSL module and a short repeated fragment; the
adapter selects the largest canonical BSL stream and exposes one public
module as `Модуль Web-сервиса`, `Модуль HTTP-сервиса`, or
`Модуль сервиса интеграции`. Handler names decoded by
`metadata.object.properties` can therefore be followed directly into their
live SQL module routines.
- Exact extension objects are resolved by the same public `kind` + `name` or
`ref` selectors as base objects. `metadata.object.modules` also returns form
modules owned by the selected object, with qualified 1C names and without
exposing CAS keys unless `include_storage=true`.
- The same module APIs expose the four configuration-level modules through the
public `Configuration.<Name>` selector: ordinary application, external
connection, managed application, and session. Runtime discovery reads the
embedded Configuration identity GUID from the current SQL root descriptor
and maps its `.0`, `.5`, `.6`, and `.7` parts internally. An intentionally
empty external-connection module is returned as an empty module instead of
being treated as missing. XML is not consulted at runtime.
- `CommonModule.<Name>` is a complete public SQL route: root discovery resolves
the object by its 1C name, and module APIs read its canonical `.0` Config
stream. Live `upo_test` discovery contains 3,400 common modules; sampled
modules decoded as BSL with public routine indexes. In public
`metadata.object.modules`, `modules.read`, and code-search responses, the
module `name`, `qualified_name`, and `display_name` are the 1C common-module
name; Config GUID/stream coordinates are exposed only with
`include_storage=true`. Common-module writes, when explicitly enabled, remain
limited to the saved-state layer.
- For `Role`, `metadata.object.properties` reads the separate SQL part
`<role-guid>.0` and returns `set_for_new_objects`,
`set_for_attributes_by_default`, `independent_rights_of_child_objects`,
object and child-object rights, per-right RLS conditions, and full
restriction templates. Standard right GUIDs are translated to public 1C
names; unrecognized platform GUIDs remain visible with
`status=unknown_right_guid` instead of being silently discarded. Permission
targets are resolved to public names even when the target is nested and has
no standalone `Config` file: `_Fld`/`_VT` routes are joined through the
read-only SQL schema to their parent object, object commands are found in the
parent's SQL `Config` payload, and integration channels are matched to the
decoded `IntegrationService` channel list. The resulting refs use public
paths such as `Catalog.<Name>.Attribute.<Name>`,
`DataProcessor.<Name>.Command.<Name>`, and
`IntegrationService.<Name>.Channel.<Name>`. These decoded identities may be
cached only in the adapter's local save index; the live 1C SQL database is
never modified.
- For `DocumentJournal`, pass `include_column_types=true` to resolve every
public column type through the referenced document attributes. This is a
supported deep read, not an undecoded property; prefer `adapter.job.start`
because large journals may require a long metadata scan.
- `data.virtual` supports `СрезПоследних`/`СрезПервых` for periodic information
registers and `Остатки`/`Обороты`/`ОстаткиИОбороты` for accumulation
registers. Exact dimension values are passed in `filters`. At least one
dimension filter is required by default; an intentional broad query must set
`allow_full_scan=true`. Accounting-register totals are reported as
`unsupported_register` until account and subconto semantics are resolved for
the selected register; raw movements remain readable.
- All `data.*` methods publish the same name-first object selector contract in
`help.methods`: callers may pass `object_ref`, `ref`, `kind/name/guid`, or
MCP aliases `object_type/object_name/object_guid`. Prefer `object_ref` with a
1C code-style name such as `Справочники.Номенклатура` when a method also
needs `record_ref` or `recorder_ref`; a record reference is never treated as
the metadata object name.
- `metadata.support.decode` accepts the same optional public object selectors.
When `ref` or `kind/name` is supplied, the adapter resolves the metadata GUID
internally and returns the effective supplier-support rule for that named
object; callers do not need to discover or pass storage identifiers.
- `metadata.code_index.build` accepts an optional public object selector for a
targeted local-cache refresh. A named base object is resolved through
`Config`, while an extension object with `extension_guid` uses
`ConfigCASSave`; omitting the selector keeps the bounded global `ConfigCAS`
scan. The index remains a local derivative cache and never writes to the 1C
database.
- `metadata.form.owner_index.build` keeps the owner selector and form selector
separate. Use `ref`/`kind/name` for the owning 1C object and `form` or
`form_name` for the nested form. For example,
`ref=Обработки.ОбменДанными, form_name=ФормаОбмена` searches the owner by
`ОбменДанными` and indexes only the named form; the two names are not
substituted for one another.
- `metadata.form.command_button.verify` uses the same owner/form separation and
publishes `command_name`, `button_name`, and `handler_name` as distinct child
selectors. Saved forms with the same name are matched against owner evidence
before verification, so a form belonging to another object is not selected
merely because its form name matches.
- `metadata.form.command_button.write` uses the same disambiguation before it
creates any proposal. `object_guid` identifies the owner and `form_guid`
identifies the nested form; they are never substituted for one another.
Name-first selection does not weaken the write workflow:
`allow_saved_state_write`, repository apply checks,
`allow_sql_saved_state_apply`, verification, and rollback guards remain
mandatory in their existing execution modes.
- `metadata.form.write_target.resolve` and
`metadata.form.write_target.verify` use the same public hierarchy:
`ref`/`kind`/`name` select the form owner, `form_name`/`form_guid` select the
nested form, and `element`/`command`/`attribute` select the child target.
`object_guid` is never treated as a nested `form_guid`.
- `metadata.form.element.write` and `metadata.form.element.write_apply` pass
that hierarchy through unchanged when resolving the concrete saved-state
file. An owner `object_guid` therefore cannot bypass name-first form
resolution. Planning remains opt-in and SQL apply still requires the
existing explicit apply and repository gates.
- `metadata.form.target.move` resolves the owner and nested form before it
resolves `from_element` and `to_element`; structural moves cannot select a
same-named form owned by another object. Its write/apply/rollback gates are
unchanged.
- `metadata.form.write_matrix.build` and `.smoke` use the same owner/form
hierarchy while resolving the saved-state file. The build operation is
read-only; smoke remains restricted to explicit apply-and-rollback.
- `metadata.write_learning.capture_before` and `.capture_after` also accept
the public owner `ref` plus a separate form selector. They write only local
learning artifacts; the selected 1C saved-state file is read, not modified.
- `metadata.saved_state.forms.search` accepts the same owner scope and filters
decoded saved forms by owner evidence before returning them. Its default
response contains the public owner ref, form name, qualified name, and
name-based selectors for matched elements, commands, and attributes.
SQL files, GUID identities, internal brace paths/markers, and low-level
writable-property coordinates are returned only with
`include_storage=true`. `form_guid` remains a separate exact diagnostic
selector. The method is read-only.
- `metadata.saved_state.modules.search` accepts a public module-owner `ref` or
`kind/name/guid`, resolves the internal saved-state prefix itself, and keeps
`file_name`/`stream_index` as opt-in diagnostic selectors. By default its
rows contain only the 1C owner, nested form, module role, qualified name,
source preview, and a semantic selector. SQL tables/files, GUID identities,
hashes, `module_ref`, and low-level write targets are returned only with
`include_storage=true`. Callers do not need to know an owner GUID for
name-first saved-code search.
- `code.write` is the public name-first write facade. It accepts the module
owner through `ref` or `kind/name/guid`, with `routine_name` as a separate
child selector, then resolves the concrete saved-state module internally.
`metadata.module.write_apply` remains the guarded low-level apply operation
for an already resolved `module_ref`.
- `templates.areas.find` accepts a public template ref such as
`Макеты.ПечатнаяФорма`. The template selector, named-area selector
(`area_name`/`area_query`), and low-level direct route are separate MCP
fields; normal callers do not need a storage route.
- `metadata.cache.lookup` accepts a public object `ref` in addition to
`kind/name/guid`. Its result is only a local identity-cache hint; operations
that require current evidence still verify against live SQL.
- `metadata.module_owner_cache.prune` accepts the cached module owner through
a public `ref` or `kind/name` and resolves `owner_guid` internally. Generated
`module_ref` values remain valid for narrow follow-up cleanup. The method
changes only adapter-local SQLite state, never the 1C SQL database; use
`dry_run=true` to inspect the matching count without deleting cache rows.
- `metadata.module_owner_cache.backfill` incrementally builds the reverse
`module_ref -> 1C object` map from current metadata. One call processes a
bounded object page and returns `next_cursor` (`kind_index`, `kind`,
`offset`) until `complete=true`. The discovered public owner is propagated
to existing lexical/vector code-index rows, including the matching
active/saved-state table pair. By default objects without code-index rows
are skipped so the operation remains fast; `deep=true` explicitly enables
their slower metadata-module decoding. This changes adapter-local SQLite
only.
- For backward compatibility, a legacy bare `guid` without an owner selector
may still identify a form. `object_guid` never gets that legacy treatment.
- Logical schema results are cached briefly. `refresh_cache=true` forces a live
metadata decode after a configuration change.
- `metadata.objects.list`: lists base/effective metadata objects only. It must
not be used with `extension`; extension-scoped queries such as `test2` must
use `extension.objects.find` or `metadata.definition.find` with `extension`.
- `extension.objects.find`: lists extension objects from the current working
programming view by default. `state=working` overlays saved rows from
`ConfigCASSave` over applied extension rows; saved-only objects are returned
too. Results carry `activation_state`: `active`, `saved_override`, or
`saved_only`.
- `metadata.definition.find`: resolves public names and references such as
`Обработка.<Name>` or `Document.<Name>`. When exactly one metadata object is
found, it is promoted to top-level `object`; `related_selectors` lists the
next safe calls allowed by the object's capabilities, including card/full
reads and scoped `code.search`/`modules.search` selectors for module-capable
objects. These related selectors include `ref` when the object kind and name
are known.
- `modules.search`: searches decoded BSL and returns matches with
`read_selector.method="modules.read"`. The selector may contain an opaque
`module_ref`; pass it through unchanged. When the owner is resolved, the same
selector also includes the public owner fields such as `kind`, `name`, `guid`,
and `ref`. For extension programming, `state=working` is the default and
searches `ConfigCASSave` first, including saved-only form/module payloads that
are not applied yet. Use `state=active` only when intentionally checking the
applied extension; use `full_scan=true` only for broad active `ConfigCAS`
fallback scans.
- `modules.read`: reads a module by public object selector or opaque
`module_ref`. Public responses include `origin` layer evidence even when the
owner object is not fully recovered: `Config` means applied configuration,
`ConfigSave` means base saved state, `ConfigCASSave` means saved state that
still needs owner/layer evidence for base-vs-extension choice, and unresolved
`ConfigCAS` means `cas_reference` with
`write_surface=requires_owner_resolution`.
- `code.search`: agent-facing search wrapper. Items contain
`read_selector.method="code.read"` and can be read directly by `code.read`.
If `modules.search` resolved the owner, `code.search` preserves the owner
selector fields while changing the read method to `code.read`. Scoped calls
may pass `module_ordinal` together with `ref`/`kind`/`name`/`guid`; the
response must stay a public `onec_code_search.v1` object. Items also carry
public `origin` evidence from `modules.search`, so the agent can see base,
saved-state, extension, or unresolved CAS provenance before reading the full
code fragment. `state` is passed through to `modules.search`; the MCP
`source_state=working` policy maps to this `state=working` mode.
- `code.read`: wraps module/routine reads for agent-facing code analysis. It
accepts either `routine_name` or the inclusive `line_start`/`line_end` range.
A focused request may use a previously decoded local code-index snapshot
(`source.kind=code_index_cache`, `freshness.verified_against_sql=false`) to
avoid decoding a large container again; pass `prefer_code_index=false` for
the normal live SQL decode path. It must preserve the module `origin`
evidence from `modules.read` so write planning can still distinguish base,
saved state, extension, or unresolved CAS references.
- `metadata.adapter.audit`: reports recognized metadata kinds, public kind
counts, missing supported kinds, and unmapped DBNames roles. Every
`missing_supported_kinds` item has
`presence_status=supported_absent_in_selected_base`: absence in one
infobase is not reported as absence of adapter implementation.
- Base root discovery includes the configuration object itself, command groups,
document numerators, external data sources, and integration services. The
root collection UUID map is verified against object UUIDs from the XML export
rather than inferred from collection position alone.
Generate a reproducible live coverage matrix without putting adapter or SQL
credentials in a file:
```text
python scripts/audit_1c_adapter_coverage.py --base-id upo_test --output reports/1c-adapter-coverage.json
```
The script reads the adapter bearer token from `ONEC_ADAPTER_TOKEN` and never
reads or prints the SQL password.
Rare-kind regression fixtures for `CalculationRegister`, `Sequence`, and the
legacy `Interface` are checked separately:
```text
python scripts/check_1c_metadata_kind_fixtures.py --live
```
The fixture checker is read-only. It reuses one extension saved-state query for
all fixtures on the same layer and does not force the slower active
`ConfigCAS` full scan. It requires an explicit dedicated-base mapping for
`Interface`.
The manifest pins the required Designer version and an external structural
reference. Use `scripts/export_1c_extension_sources.ps1` to export `test2`
through operating-system integrated authentication; the helper accepts no
infobase user or credential parameters and never writes platform SQL.
For a resumable read-only application-data audit, run the full public chain for
one object of every data-bearing metadata kind:
```text
python scripts/audit_1c_adapter_coverage.py
--base-id upo_test
--sample-data-reads
--workers 2
--timeout 90
--checkpoint reports/1c-adapter-data-checkpoint.json
--output reports/1c-adapter-coverage-live.json
```
The checkpoint is replaced atomically after every completed operation and
kind. Resume an
interrupted run with `--resume`; add `--retry-degraded` to rerun only timed-out
or failed kinds while retaining successful evidence. Each data check records
durations and statuses for `data.schema`, `data.list`, `data.count`, and
`data.get` when the sampled row has a public reference key. Register rows with
no reference key report `data.get=not_applicable` rather than a false failure.
An XML export can be used as an independent property-schema reference. The
analyzer keeps the base configuration and each extension as separate layers:
```text
python scripts/analyze_1c_xml_metadata.py --include-artifacts --output reports/1c-xml-metadata-analysis.json
```
Owner resolution:
- Search results distinguish module readability from owner resolution. A module
can be readable through `read_selector` even when `owner.status=unresolved`.
- Use `counts.owner_resolved`, `counts.owner_unresolved`,
`counts.owner_scan_limit_hit`, and `diagnostics.owner_resolution` to decide
whether to narrow the selector or increase `owner_scan_limit`.
- Do not request `include_storage=true` only to read a found module; use the
public `read_selector` first.
Working source state:
- For programming/designer analysis, agents must query the latest saved working
state first. In MCP calls this is `source_state=working`; the MCP bridge maps
it to REST `state=working` for `extension.objects.find`, `modules.search`,
`code.search`, and `metadata.resolve_overrides`.
- `source_state=applied` maps to REST `state=active` and intentionally ignores
saved rows. Use it only when checking what is already applied.
- `source_state=all` maps to REST `state=both` for side-by-side inspection. The
response keeps `activation_state` markers such as `saved_only`,
`saved_override`, and `active`, so agents can tell which findings are not
applied yet.
- `code.read state=both` reads the saved layer and the active layer as two
independent views. The response sets `current_state.source=both`, returns
ordered `layers` entries for `saved_state` and `active`, and includes
`comparison.both_present` plus `comparison.differs`. When `include_text=true`,
top-level `text` is the effective programming text: saved-state text if it
exists, otherwise active text. `text_source` names the layer used.
For extension form modules, the saved counterpart is matched by extension,
logical form owner, and form GUID rather than by assuming identical active
and saved CAS file names.
- `code.search state=both` also returns a mixed view for saved CommonForm code:
saved-state matches are listed first, active matches are fetched with an
independent `state=active` pass, and `counts.saved_matches` /
`counts.active_matches` show layer coverage.
- If an extension object exists only in `ConfigCASSave`, it is still part of the
working programming surface. Analysis and write planning must not discard it
just because activation has not happened yet.
Smoke check:
```text
python scripts/smoke_1c_mcp_selector_chain.py --json
```
This offline smoke validates generic MCP selector chains such as
`metadata.definition.find -> related_selectors.code_search -> code.search ->
item.read_selector -> code.read`. Examples use placeholders only and must not
contain concrete configuration object names.
Optional live smoke:
```text
python scripts/smoke_1c_mcp_selector_chain.py
--live
--transport rest
--adapter-url <1c-rest-adapter-url>
--base-id <base-id-from-project-context>
--json
```
To run the same live chain through the MCP proxy instead of direct REST `/rpc`,
use:
```text
python scripts/smoke_1c_mcp_selector_chain.py
--live
--transport mcp
--mcp-url <1c-mcp-proxy-url>
--base-id <base-id-from-project-context>
--json
```
The live mode discovers a module-capable metadata object through
`metadata.objects.list`, verifies `metadata.definition.find` related selectors,
reads the first module through `modules.read` using the returned selector,
then derives a search token from module text or routine metadata and verifies
`code.search -> item.read_selector -> code.read`. It does not hard-code object
names or BSL fragments, and it passes object selectors through instead of
reconstructing them from display text. MCP transport performs the same calls through
`initialize`, `Mcp-Session-Id`, and `tools/call` + `onec_request`.
## Question Routing
Command:
```text
python scripts/route_1c_question.py
--text <UserQuestionOrTask>
--index <unified object route index>
--view effective|base
```
Safe Unicode command shape:
```text
python scripts/route_1c_question.py
--text-b64 <utf8-base64 UserQuestionOrTask>
--index <unified object route index>
```
Output schema:
```text
onec_question_route.v1
```
Purpose:
- classify a user question before tools are selected;
- route documentation questions to official-docs RAG;
- route concrete configuration facts to the fact resolver;
- detect source-risk phrases such as "in the RAG example" and require current
configuration confirmation before code generation;
- extract explicit facts such as `Справочник.Номенклатура.Артикул` and
phrased facts such as "реквизит Артикул у справочника Номенклатура".
Routes:
- `docs_rag`: only official documentation context is needed.
- `current_config_fact`: current configuration facts are needed before answer or
code.
- `mixed_docs_and_current_config`: use official docs for platform behavior, but
confirm object/member facts through the adapter first.
- `needs_clarification`: neither docs nor current-config target was clear.
Contract check:
```text
python scripts/check_1c_question_router.py
--index <unified object route index>
--output reports/1c-question-router.json
```
## Agent Intake
Command:
```text
python scripts/build_1c_agent_intake.py
--text <UserQuestionOrTask>
--index <unified object route index>
--view effective|base
```
Output schema:
```text
onec_agent_intake.v1
```
Purpose:
- create the first packet an agent should inspect before answering or writing
code;
- include the question route, source policy, confirmed/unresolved current-base
facts, answer/code policy, and next tool commands;
- make the "example is not current fact" rule machine-readable through
`source_policy.examples_are_current_facts=false`;
- set `answer_policy.code_generation_allowed=false` when required current facts
are missing or not checked.
HTTP console API:
```text
POST /api/1c/intake
{
"question": "...",
"source_path": "reports/1c-sql/upo/unified-object-route-index.json",
"view": "effective"
}
```
## Saved State Object Compare
Command:
```text
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/compare_1c_saved_state_objects.ps1
-Server <SqlServer>
-Database <SqlDatabase>
-User <SqlUser>
-Password <SqlPassword>
-Output <json>
```
Normal agent command:
```text
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build_1c_saved_state_object_report.ps1
-Server <SqlServer>
-Database <SqlDatabase>
-User <SqlUser>
-Password <SqlPassword>
-OutputDir <directory>
[-SkipMarkdown]
```
Repeated observation command:
```text
powershell -NoProfile -ExecutionPolicy Bypass -File scripts/watch_1c_saved_state_once.ps1
-Server <SqlServer>
-Database <SqlDatabase>
-User <SqlUser>
-Password <SqlPassword>
-OutputRoot <directory>
python scripts/list_1c_saved_state_watch_runs.py
--root <directory>
[--limit <N>]
[--only-with-delta]
[--only-changed]
--output <json>
[--skip-markdown]
[--skip-check]
python scripts/check_1c_saved_state_watch_run_list.py
--list <SavedStateWatchRunListJson>
--output <json>
python scripts/get_1c_saved_state_latest_watch_run.py
--root <directory>
[--require-delta]
[--require-changed]
--output <json>
[--skip-markdown]
[--skip-check]
python scripts/check_1c_saved_state_latest_watch_run.py
--latest <SavedStateLatestWatchRunJson>
--output <json>
python scripts/render_1c_saved_state_latest_watch_run_markdown.py
--latest <SavedStateLatestWatchRunJson>
--output <markdown>
python scripts/render_1c_saved_state_watch_run_list_markdown.py
--list <SavedStateWatchRunListJson>
--output <markdown>
```
Markdown rendering:
```text
python scripts/render_1c_saved_state_object_report_markdown.py
--report <SavedStateObjectReportJson>
--output <markdown>
```
Contract check:
```text
python scripts/check_1c_saved_state_object_report.py
--report <SavedStateObjectReportJson>
--output <json>
python scripts/check_1c_saved_state_watch_once.py
--manifest <SavedStateWatchRunJson>
--output <json>
python scripts/render_1c_saved_state_watch_once_markdown.py
--manifest <SavedStateWatchRunJson>
--output <markdown>
```
Report-to-report delta:
```text
python scripts/compare_1c_saved_state_object_reports.py
--before <PreviousSavedStateObjectReportJson>
--after <CurrentSavedStateObjectReportJson>
--output <json>
[--skip-markdown]
[--skip-check]
```
```text
python scripts/check_1c_saved_state_object_report_delta.py
--delta <SavedStateObjectReportDeltaJson>
--output <json>
python scripts/render_1c_saved_state_object_report_delta_markdown.py
--delta <SavedStateObjectReportDeltaJson>
--output <markdown>
```
Object change lookup:
```text
python scripts/list_1c_saved_state_object_changes.py
--report <SavedStateObjectReportJson>
[--layer base|extension]
[--kind <Kind>]
[--payload-role <PayloadRole>]
[--active-missing true|false]
[--text-diff true|false]
--output <json>
```
```text
python scripts/get_1c_saved_state_object_change.py
--report <SavedStateObjectReportJson>
--name <ConfiguratorObjectName>
--output <json>
```
Output schema:
```text
onec_saved_state_object_comparison.v1
onec_saved_state_object_detail.v1
onec_saved_state_object_report.v1
onec_saved_state_object_report_check.v1
onec_saved_state_watch_once.v1
onec_saved_state_watch_once_check.v1
onec_saved_state_watch_run_list.v1
onec_saved_state_watch_run_list_check.v1
onec_saved_state_latest_watch_run.v1
onec_saved_state_latest_watch_run_check.v1
onec_saved_state_object_report_delta.v1
onec_saved_state_object_report_delta_check.v1
onec_saved_state_object_change_list.v1
onec_saved_state_object_change.v1
```
Purpose:
- compare saved-but-not-applied SQL state with active state in 1C object terms;
- provide a single read-only report command that runs comparison, exports the
required payload evidence, performs object detail analysis, and writes a
Markdown summary by default;
- provide a one-shot watch command that stores timestamped observations and
compares the new observation with the previous one when available; it writes
a Markdown watch summary by default unless `-SkipMarkdown` is used;
- list timestamped watch observations without reading SQL, including latest
run, linked artifacts, check statuses, and delta counts; write Markdown next
to the run-list JSON by default and run a contract check when `--output` is
used;
- return the latest matching watch observation directly, with optional
requirements for a delta or actual delta changes; run a contract check by
default and write Markdown when `--output` is used;
- include `agent_summary` in `onec_saved_state_object_report.v1` so agents can
see changed 1C object names, changed payload parts, active-missing part
counts, payload roles, and short semantic term hints without parsing Markdown
or full detail payloads;
- compare `ConfigSave` with `Config` and `ConfigCASSave` with `ConfigCAS`;
- return `object_changes` as configurator objects such as
`ОбщийМодуль.HttpBridgeКлиент` or extension forms;
- keep `FileName`, byte sizes, and hashes under storage evidence;
- keep `root`, `versions`, and extension `configinfo` under `system_changes`.
- optionally analyze changed object payloads for text deltas, added/removed
words, and saved form/module string samples.
- when extension manifest summary and active `ConfigCAS` export are provided,
detail analysis resolves extension saved parts to active CAS keys before
comparing payloads.
- render the JSON report as compact Markdown for human review while keeping 1C
configurator names first and SQL storage names as evidence.
- classify changed payload parts with roles such as `bsl_module_text`,
`form_descriptor`, `form_body`, `primary_payload`, or `metadata_payload`;
- keep raw word diffs in detail evidence, but expose filtered
`semantic_hints.added_terms` and `semantic_hints.removed_terms` for agent
triage.
- validate each generated report with a final read-only contract check before
treating it as reliable agent input.
- compare two saved-state report observations by 1C object name and stable
payload-part fingerprints when the user continues editing between checks;
write Markdown and a contract-check JSON next to the delta JSON by default
when `--output` is used.
- support object-level lookup from a saved-state report by full name, short
configurator name, synonym, suffix, or contains match; ambiguous matches must
return candidates rather than selecting one silently.
- support compact changed-object listing and filtering by layer, kind,
extension, payload role, text diff presence, and missing active counterpart.
## Object Context Search
Command:
```text
python scripts/search_1c_object_context.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--text <SearchText>
--view effective|base|extension
--extension <ExtensionName>
--search-code
--max-form-items <N>
--limit <N>
--output <json>
```
Output schema:
```text
onec_object_context_search.v1
```
Purpose:
- search one resolved object by human/configurator terms;
- search metadata attributes, tabular section names, forms, form items, form
attributes, form commands, form events, module names, and optionally BSL code
lines;
- keep origin/effective action evidence so matches from extensions are not
confused with base configuration matches;
- return file paths and line snippets for code hits, allowing the agent to
follow up with `get_1c_module.py --routine` or module snippet reads.
## Task Context Plan
Command:
```text
python scripts/plan_1c_task_context.py
--index <unified object route index>
--text <TaskText>
--view effective
--max-objects <N>
--max-terms <N>
--max-matches <N>
--output <json>
```
Output schema:
```text
onec_task_context_plan.v1
```
Purpose:
- turn a user task into a read-only investigation plan;
- find likely metadata object candidates by configurator-visible object names
and synonyms, using kind hints such as "document" or "catalog";
- for each candidate, gather brief context and search the object for task
terms across metadata, forms, commands, events, modules, and BSL code;
- produce recommended follow-up reads such as object metadata, form context,
and exact module reads;
- keep write support explicitly blocked by `docs/1c-write-path-safety.md`.
## Task Evidence Bundle
Command:
```text
python scripts/build_1c_task_evidence.py
--index <unified object route index>
--text <TaskText>
--view effective
--max-objects <N>
--max-module-chars <N>
--code-snippet-radius <N>
--max-code-snippets <N>
--output <json>
```
Output schema:
```text
onec_task_evidence_bundle.v1
```
Purpose:
- materialize the read-only task plan into a compact evidence bundle for code
generation or human review;
- include full effective metadata summaries, selected form contexts, selected
module snippets, and targeted code snippets around search hit lines;
- preserve base/extension origin, file paths, form XML paths, module paths, and
line numbers;
- keep large files bounded by explicit limits while retaining focused evidence
for relevant code found deep inside large modules.
## Task Change Proposal
Command:
```text
python scripts/propose_1c_task_changes.py
--evidence <TaskEvidenceBundleJson>
--output <json>
```
Output schema:
```text
onec_task_change_proposal.v1
```
Purpose:
- turn a read-only evidence bundle into a structured implementation proposal;
- infer broad task intents such as form command, attribute, lifecycle, or
inspection;
- separate extension-first write candidates from base/read-only reference
files;
- identify existing form commands/items, metadata attributes, and related code
hits before any patch is generated;
- use full 1C paths as change targets, and keep local names only when they are
bound to a concrete object, form, module, routine, or symbol context;
- keep the proposal under the write safety contract: no SQL/Config writes and
no automatic production update/apply.
Markdown rendering:
```text
python scripts/render_1c_task_proposal_markdown.py
--proposal <TaskChangeProposalJson>
--output <markdown>
```
The Markdown report is for human review and should mirror the JSON proposal,
not replace it as machine-readable evidence.
Safety check:
```text
python scripts/check_1c_change_proposal_safety.py
--proposal <TaskChangeProposalJson>
--output <json>
```
Output schema:
```text
onec_change_proposal_safety_check.v1
```
Purpose:
- gate future patch generation on machine-checkable safety rules;
- require write candidates to live in the preferred extension origin and path;
- verify candidate/reference paths exist;
- reject direct SQL/Config/ConfigSave/ConfigCAS write targets;
- preserve the required gates that still block real write/apply operations.
## Patch Workspace
Command:
```text
python scripts/create_1c_patch_workspace.py
--proposal <TaskChangeProposalJson>
--output-root <directory>
--slug <name>
--output <json>
```
Output schemas:
```text
onec_patch_workspace_creation.v1
onec_patch_workspace_manifest.v1
```
Purpose:
- create a safe local workspace for future generated edits;
- run the proposal safety check before copying anything;
- copy only extension write candidates into `original/` and `working/`;
- keep `proposal.json`, `safety.json`, `manifest.json`, and `README.md`
beside the copies;
- require edits to happen only under `working/`.
Diff command:
```text
python scripts/check_1c_patch_workspace_integrity.py
--workspace <PatchWorkspaceDir>
--output <json>
python scripts/check_1c_patch_source_freshness.py
--workspace <PatchWorkspaceDir>
--output <json>
python scripts/validate_1c_patch_workspace_semantics.py
--workspace <PatchWorkspaceDir>
--output <json>
python scripts/edit_1c_bsl_routine.py
--workspace <PatchWorkspaceDir>
--relative-path <ManifestBslModuleRelativePath>
--operation append|replace|upsert
--routine-text-b64 <Utf8Base64BslRoutine>
[--keep-on-failure]
--output <json>
python scripts/edit_1c_form_command.py
--workspace <PatchWorkspaceDir>
--relative-path <ManifestFormXmlRelativePath>
--operation append|replace|upsert
--name <CommandName>
--title <RussianTitle>
--action <BslHandlerName>
[--tooltip <RussianTooltip>]
[--id <CommandId>]
[--keep-on-failure]
--output <json>
python scripts/edit_1c_form_button.py
--workspace <PatchWorkspaceDir>
--relative-path <ManifestFormXmlRelativePath>
--operation append|replace|upsert
--parent-name <ParentFormItemName>
--name <ButtonName>
--title <RussianTitle>
--command-name <ExistingCommandName>
[--id <ButtonId>]
[--keep-on-failure]
--output <json>
python scripts/add_1c_form_button_workflow.py
--workspace <PatchWorkspaceDir>
--form-relative-path <ManifestFormXmlRelativePath>
--bsl-relative-path <ManifestFormModuleRelativePath>
--operation append|replace|upsert
--routine-text-b64 <Utf8Base64BslRoutine>
--command-name <CommandName>
--command-title <RussianCommandTitle>
--command-action <BslHandlerName>
--button-parent-name <ParentFormItemName>
--button-name <ButtonName>
--button-title <RussianButtonTitle>
[--keep-on-failure]
--output <json>
python scripts/diff_1c_patch_workspace.py
--workspace <PatchWorkspaceDir>
--output <json>
python scripts/create_1c_patch_bundle.py
--workspace <PatchWorkspaceDir>
--output-root <PatchBundleRoot>
--slug <BundleSlug>
--output <json>
python scripts/check_1c_patch_bundle.py
--bundle-dir <PatchBundleDir>
[--zip <PatchBundleZip>]
--output <json>
python scripts/create_1c_extension_staging_from_bundle.py
--bundle-dir <PatchBundleDir>
--output-root <ExtensionStagingRoot>
--slug <StagingSlug>
--output <json>
python scripts/check_1c_extension_staging.py
--staging-dir <ExtensionStagingDir>
--output <json>
python scripts/check_1c_extension_runner_config.py
--config <ExtensionRunnerConfigJson>
--output <json>
python scripts/create_1c_extension_validation_plan.py
--staging-dir <ExtensionStagingDir>
[--runner-config <SafeRunnerConfigJson>]
--output <json>
--markdown-output <markdown>
python scripts/create_1c_extension_validation_evidence.py
--plan <ExtensionValidationPlanJson>
[--output-root <EvidenceRoot>]
--output <json>
python scripts/check_1c_extension_validation_evidence.py
--plan <ExtensionValidationPlanJson>
[--evidence-root <EvidenceRoot>]
--output <json>
python scripts/check_1c_extension_validation_release.py
--plan <ExtensionValidationPlanJson>
[--evidence-root <EvidenceRoot>]
--output <json>
python scripts/render_1c_extension_validation_release_markdown.py
--release-check <ExtensionValidationReleaseCheckJson>
--output <markdown>
python scripts/check_1c_patch_preflight.py
--workspace <PatchWorkspaceDir>
--output <json>
python scripts/render_1c_patch_preflight_markdown.py
--preflight <PatchPreflightJson>
--output <markdown>
```
Output schema:
```text
onec_patch_workspace_integrity.v1
onec_patch_source_freshness.v1
onec_patch_workspace_semantic_validation.v1
onec_bsl_routine_edit.v1
onec_form_command_edit.v1
onec_form_button_edit.v1
onec_form_button_workflow.v1
onec_patch_workspace_diff.v1
onec_patch_bundle.v1
onec_patch_bundle_creation.v1
onec_patch_bundle_check.v1
onec_extension_staging.v1
onec_extension_staging_creation.v1
onec_extension_staging_check.v1
onec_extension_runner_config_check.v1
onec_extension_validation_plan.v1
onec_extension_validation_evidence_manifest.v1
onec_extension_validation_evidence_check.v1
onec_extension_validation_release_check.v1
onec_patch_preflight.v1
```
Purpose:
- verify `original/` hashes still match the manifest before any diff/package
step;
- verify source extension files still match the hashes recorded when the patch
workspace was created, so stale patches cannot overwrite newer source files;
- verify every manifest file exists under both `original/` and `working/`;
- flag unexpected files under `original/` as errors and unexpected files under
`working/` as warnings;
- validate edited workspace semantics before review: parse `Form.xml`, parse
BSL routines, reject duplicate routines/commands, check basic BSL block
balance, and verify form command actions have matching form-module routines
when both files are in the workspace;
- edit one BSL procedure/function under `working/` through a manifest-bound
operation: append a new routine, replace an existing routine, or upsert one
routine; the command validates the full workspace semantics after writing and
rolls the file back by default when validation fails;
- edit one form command under `working/` through a manifest-bound operation:
append a new `<Command>`, replace an existing command, or upsert one command;
the command chooses a safe numeric id when omitted, validates the full
workspace semantics after writing, and rolls the file back by default when
validation fails;
- edit one visible form button under `working/` through a manifest-bound
operation: append/replace/upsert one `<Button>` under a named parent form item
and bind it to an existing form command; the command validates the full
workspace semantics after writing and rolls the file back by default when
validation fails;
- add a complete form button workflow atomically: BSL handler, form command,
and visible button. This is the preferred agent operation when a user asks to
add a button. It snapshots all `working/` manifest files and restores them if
any step fails, unless `--keep-on-failure` is explicitly set;
- compare `original/` and `working/` files from a patch workspace;
- create a review bundle only when preflight status is `ready_for_review`.
The bundle copies modified `working/` files, `manifest.json`,
`preflight.json`, `preflight.md`, and `diff.json` into a review directory and
zip archive. It self-checks the created bundle and does not apply changes to
source extension files or SQL;
- validate a review bundle independently: check manifest/preflight/diff
consistency, copied modified-file hashes, required review files, and zip
archive contents;
- create a disposable extension XML staging copy from a validated review bundle.
This copies the source extension directory to staging, overlays bundle files,
writes `_codex_staging_manifest.json`, and still does not modify source
extension files or SQL. The creation command validates the staging copy before
returning success;
- validate a disposable extension XML staging copy independently: check staging
manifest schema, safety flags, staged file hashes, source extension freshness,
and the recorded review bundle;
- validate runner configuration for disposable 1C validation: require
`onec_extension_runner_config.v1`, reject production-like base references,
reject secrets/credentials in the config file, and require
`disposable_base_confirmed=true`;
- create a disposable-base validation plan for a staged extension. The plan is
read-only: it does not launch 1C, does not modify SQL/source files, marks
production bases as forbidden, lists required Designer/Enterprise checks, and
records the evidence files a future runner must produce. If runner config is
provided, it must pass the runner-config check;
- create pending manual evidence templates from a validation plan. This only
creates files to be filled with disposable-base 1C logs and confirmations; it
never marks validation as passed;
- check filled validation evidence: every expected evidence file must exist and
no file may still contain the pending template markers. Evidence must state
explicit `passed`, `success`, or `ok` status; `changed-objects-smoke.json`
must have passed status for every changed object. Evidence files are also
scanned for secret-like key/value text;
- aggregate final validation gates for human review: validation plan must be
ready, staging must still pass, evidence must pass, safety flags must still
forbid production/SQL/source writes. The result can only become
`validated_for_human_review`; it never authorizes automatic production apply;
- render the final validation release check as a human-readable Markdown report
that keeps the no-automatic-production-apply safety message visible;
- return file hashes, status, unified patches, line counts, and hunk counts;
- aggregate proposal safety, workspace integrity, source freshness, semantic
validation, and diff gates into a single preflight status: `blocked`,
`ready_for_editing`, or `ready_for_review`;
- provide the diff evidence needed before any extension packaging or human
approval step.
## Object Metadata
Command:
```text
python scripts/get_1c_object_metadata.py
--kind <ConfiguratorKind>
--name <ConfiguratorName>
--view effective|base|extension
--extension <ExtensionName>
--index <unified object route index>
```
Output schema:
```text
onec_object_metadata.v1
```
Purpose:
- return agent-facing metadata in 1C terms;
- default to `view=effective`, the current working metadata picture;
- support `view=base` for the main configuration only;
- support `view=extension --extension <name>` for one extension's additions
and modifications;
- keep `origin.layer`, `origin.extension`, and `effective_action` in JSON while
allowing human-facing answers to stay concise.
Example expectations for `Документ.ПриходнаяНакладная`:
```text
effective: 66 attributes, includes ДатаСоздания from ДоработкаРарус
base: 65 attributes, excludes ДатаСоздания
extension ДоработкаРарус:
- ДатаСоздания: added
- ДокументОснование: modified
```
## Read Object View
Command:
```text
python scripts/read_1c_object_view.py
--kind <Kind>
--name <Name>
--view effective|base|extension
--extension <ExtensionName>
--summary <structured metadata DBNames summary>
--validation <predicted column validation>
--route-index <unified object route index>
--output-dir <run output directory>
```
Unicode-safe shell variant:
```text
--name-b64 <utf8-base64-name>
```
Output schema:
```text
onec_sql_read_view.v1
```
Purpose:
- resolve the visible 1C object name first;
- locate enriched metadata by `kind/name`;
- if the object is absent from the prepared summary, build a metadata card from
resolved XML and DBNames evidence;
- build SQL projection;
- execute SQL read after live SQL table-column validation;
- resolve simple references;
- resolve composite references;
- resolve composite value branches;
- attach enum presentations from metadata routes;
- return an agent-facing object view with raw evidence preserved.
Read views follow the same layer model as metadata:
```text
effective: current working data, including active extension companion tables
base: base configuration tables only
extension: standard identity fields plus fields added/modified by one extension
```
Agent-facing metadata should present 1C types in Russian by default, matching
how programmers usually write/read 1C code: `СправочникСсылка.Номенклатура`,
`ДокументСсылка.ПриходнаяНакладная`, `ПеречислениеСсылка.ВидОперации`,
`Строка`, `Число`, `Булево`, `Дата`. Canonical XML/storage types such as
`cfg:CatalogRef.*` and `xs:boolean` remain in `value_type.types` for internal
adapter logic and for explicit debug/storage views.
Object metadata is effective metadata, not base-only metadata. Active extension
overlays must be applied before returning attributes, tabular sections, forms,
modules, or code context. Extension-added attributes are returned alongside base
attributes with source metadata; extension-adopted objects keep override
evidence in `extension_overrides`. A base-only answer is a debug/storage view,
not the default agent-facing answer.
For SQL reads, active extensions can move effective data into companion tables
with `Xn` suffixes, for example `_Document675X1` and
`_Document675_VT8000X1`. The read executor must choose the effective live table
by schema coverage and row availability, and record that decision in
`diagnostics.effective_tables`. Agents should see only the metadata object and
fields; companion table names remain storage diagnostics.
`onec_sql_read_result.v1` may include `diagnostics.pruned_missing_columns`.
These are columns present in the metadata projection but absent from the live
SQL table at execution time. The executor removes only those confirmed-missing
columns before running `SELECT`.
## Enum Presentation Map
Command:
```text
python scripts/build_1c_enum_presentation_map.py
--index <unified object route index>
--output <json>
```
Output schema:
```text
onec_enum_presentation_map.v1
```
Purpose:
- map SQL enum `_EnumOrder` values to metadata enum value `uuid/name/synonym`;
- use exported XML route evidence as the source of enum value order;
- prefer base configuration enum XML over extension XML when the same enum name
exists in both, while keeping extension evidence available in the route index.
This command is an offline analysis aid. Runtime `data.list`/`data.get` enum
presentation is decoded from SQL metadata and does not require an XML export.
## Object Artifacts
Command:
```text
python scripts/get_1c_object_artifacts.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--output <json>
```
Output schema:
```text
onec_object_artifacts.v1
```
Purpose:
- return owner object routes;
- list related XML top objects under the owner path;
- list forms, templates, object modules, form modules, and command modules
from the exported XML filesystem evidence.
This is currently XML/filesystem backed. The SQL/CAS-backed implementation must
preserve the same output shape.
## Object Code Context
Command:
```text
python scripts/get_1c_object_code_context.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--view effective|base|extension
--extension <ExtensionName>
--output <json>
```
Output schema:
```text
onec_object_code_context.v1
```
Purpose:
- return the module map for an object without loading large BSL contents;
- keep module names in 1C terms such as `МодульОбъекта`,
`МодульМенеджера`, `МодульФормы.ФормаДокумента`, and
`МодульКоманды.<ИмяКоманды>`;
- for `view=effective`, return base modules with active extension overlays
attached under `extension_overlays`;
- for `view=base`, return only main configuration modules;
- for `view=extension --extension <name>`, return only modules from the
selected extension.
## Module Content
Command:
```text
python scripts/get_1c_module.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--module <ModuleName>
--view effective|base|extension
--extension <ExtensionName>
--routine <ProcedureOrFunctionName>
--max-chars <N>
--output <json>
```
Output schema:
```text
onec_module_content.v1
```
Purpose:
- read the requested BSL module or one routine from that module;
- for `view=effective`, include the base module and matching active extension
overlays, preserving their order and origin evidence;
- keep full file paths, relative paths, sizes, truncation markers, and line
starts so a later write path can target the exact source.
## Form Context
Command:
```text
python scripts/get_1c_form_context.py
--index <unified object route index>
--kind <Kind>
--name <Name>
--form <FormName>
--view effective|base|extension
--extension <ExtensionName>
--max-items <N>
--output <json>
```
Output schema:
```text
onec_form_context.v1
```
Purpose:
- return common forms by configurator-visible common form name, for example
`ОбщаяФорма.t_Форма` / `CommonForm.t_Форма`;
- return object-owned forms by configurator-visible object and form names, for
example forms under catalogs, documents, data processors, reports, registers,
charts, exchange plans, business processes, tasks, and other form-capable
metadata objects;
- parse `Ext/Form.xml` into agent-facing form events, items, attributes, and
commands without requiring the agent to know XML paths;
- return both raw item `title` and computed `effective_title` with
`title_resolution`, because a form item can inherit its visible title from a
bound form command, form attribute, or value-table column when its own title
is empty;
- expose `title_resolution.edit_targets.default_change_target` and
`one_off_change_target`: default changes should edit the inherited source
such as command/attribute title, while one-off form-only changes should edit
the form item title;
- keep runtime form reads SQL-only; XML paths are accepted only by offline
analysis scripts and are rejected by the running adapter;
- for `view=effective`, return the base form with active extension form
overlays attached under `extension_overlays`;
- for `view=base`, return only the main configuration form;
- for `view=extension --extension <name>`, return only the selected
extension's form structure.
Selector rules:
- `CommonForm` / `ОбщаяФорма` is a top-level metadata object kind, not a child
form of an owner object;
- `Form` is reserved for child form payloads owned by a metadata object;
- when a task says "форма <name>" without an owner, search common forms first,
then ask for or infer the owner object before falling back to global scans;
- for live SQL analysis, build `metadata.form.owner_index.build` before relying
on name-only form selectors. The index resolves `CommonForm.<name>` or
object-owned form routes through extension manifests/DBNames and the actual
ConfigCAS `.0` form payload, storing `module_ref` and `bsl_offset` for form
module reads;
- form structural edits such as adding a form command, adding a command bar
button, or inserting a new form item are Form.xml node operations. They must
not be routed through scalar saved-state property writers that only change an
existing decoded target;
- `metadata.form.command_button.write` handles the command/button case through
SQL saved-state payloads: it clones existing command and command-button nodes
from the same form, appends them with the byte-preserving `append_child`
structural edit, increments declared section counts such as
`{marker,count,record...}` when present, and uses the normal
proposal/apply/rollback gates. XML may still be used to analyze or train the
rule, but live apply remains SQL-only.
- After form command/button `apply` or `apply_and_verify`, the adapter returns
`semantic_verify` with command, button, handler routine, command-handler
link, button-command link, decoded command path, and decoded button path.
Repeated upsert calls must be idempotent and return
`idempotency.status=already_exists` instead of appending duplicate nodes.
- `metadata.form.command_button.verify` is the read-only equivalent for the
same workflow. It resolves saved-state form targets from public selectors and
returns the command/button/handler/link checks without preparing, proposing,
or applying SQL changes.
- Public command/button write and verify responses use compact saved-state
search evidence: `counts` plus `selected_form`, not the full candidate list.
- `metadata.form.write_target.verify` is a read-only preflight for existing form
element/command/attribute writes. It reports `writable_now`, `needs_prepare`,
a public `form_path` for the write node, and the `metadata.saved_state.prepare`
payload when the save layer is missing.
- `metadata.write.history` lists recent adapter write operations, including
`code.write`, or returns a specific `operation_id` with status, routed method,
target summary, backup ids, and full result for a single operation. It can
filter by `operation_method`, `status`, `routed_method`, or `backup_id`.
Pass `include_summary=true` for aggregate counts by method, status, routed
method, and operations with backups.
- `metadata.write.rollback` rolls back one saved-state backup selected by
`operation_id` or `backup_id`. It is an explicit apply operation and requires
`allow_sql_saved_state_rollback=true`.
- The deployment verification stack includes rollback safety reports:
`write-rollback-safety-smoke.json` for REST and
`write-rollback-safety-mcp-smoke.json` for MCP. These reports must show the
method in `help.methods`, readable write history, and blocked rollback when
`allow_sql_saved_state_rollback` is absent.
- `metadata.saved_state.prepare` prepares an object's saved-state working copy.
Prefer a public selector (`ref` or `kind/name`) together with
`layer=base_saved_state|extension_saved_state`. Its default response reports
the selected 1C object, active/saved semantic layers, record counts, and
readiness without exposing database/table names, storage files, hashes, or
row details. `include_storage=true` retains the low-level diagnostic response.
`plan` remains the default and performs no write; `apply` and
`apply_and_verify` still require `allow_sql_saved_state_prepare=true`.
- `metadata.saved_state.ensure` is the preferred idempotent public facade for
that operation. It resolves `ConfigSave` or `ConfigCASSave` from the public
object/extension selector, copies only missing active parts, and never asks a
user to create a missing save layer in Configurator. It remains a plan by
default; its apply modes use the same explicit SQL gate.
- `metadata.saved_state.ensure.rollback` removes only rows inserted by the
opaque receipt returned from an ensure apply. It SHA-checks every row first,
requires `allow_sql_saved_state_rollback=true`, and never touches active
`Config` or `ConfigCAS`.
- Every public RPC `next_resolution`/`next_call` entry uses `{method, params}`.
`payload` is reserved for the outer RPC request envelope and internal
apply-hint bodies; it must not be used as the arguments field of a public
follow-up. Saved-state follow-ups use the semantic contract: `layer` plus a
public object `ref` or `kind/name`. Internal `target_table`, `source_table`,
`file_name`, `file_names`, `module_ref`, object GUIDs, and
`include_storage` are not copied into public follow-up payloads. If only an
opaque storage target is known, the follow-up reports `selector_required`
instead of exposing that target.
- `metadata.saved_state.diff` is the agent-facing read-only comparison between
a saved-state module and its active source. Prefer a public 1C selector such
as `ref=Справочник.Номенклатура` or `kind/name` plus `module_ordinal`;
the adapter resolves the saved-state table and physical file internally.
Generated `module_ref` or `table` + `file_name` remain accepted for chained
tooling. Name-first responses hide storage coordinates unless
`include_storage=true`, and a missing save layer returns a name-first
`metadata.saved_state.prepare` payload. The method maps
`ConfigSave -> Config` and `ConfigCASSave -> ConfigCAS`, reads both payloads
from live SQL, and returns `changed`/`unchanged`, `needs_prepare`, current
hashes, compact text/tree diff, and
`freshness.status=live_sql_verified`.
Deployment verification persists REST/MCP smoke reports as
`saved-state-diff-smoke.json` and `saved-state-diff-mcp-smoke.json`.
- `metadata.saved_state.status` is the read-only name-first overview for a whole
save layer. Prefer `layer=base_saved_state|extension_saved_state`; the default
response reports semantic aggregate state and object/record counts without
exposing SQL tables, database names, files, hashes, or internal diff
selectors. `include_storage=true` enables the diagnostic storage view, which
accepts the backward-compatible `table=ConfigSave|ConfigCASSave`, compares
saved rows with their active source by file part, size, and SHA1, and returns
per-file `changed`, `unchanged`, or `saved_only` statuses.
- `configuration.activation.status` is the read-only activation boundary for
`saved_state -> active`. It checks both layers by default, or accepts
`layer=base_saved_state|extension_saved_state`, and delegates to the live SQL
saved-state comparison above. It never uses the code cache or vector index as
authority. `activation_required=true` means at least one `changed` or
`saved_only` object exists. If the configured scan limit is reached without a
detected difference, the result is `inconclusive` rather than a false
`up_to_date`.
- `configuration.activation.plan` uses that live status to build a read-only
handoff. When changes exist, it returns a `{method, params}` review call, a
manual Designer action (`Обновить конфигурацию базы данных`, F7), and a live
verification call whose expected status is `up_to_date`. The current adapter
does not start Designer or mutate the active configuration, even when
`ONEC_ADAPTER_ENABLE_EXTERNAL_1C` is enabled. A future execution method must
use a dedicated Designer bridge and separate explicit confirmation.
- `configuration.activation.request` creates an expiring adapter-local request
only when the live status is `activation_required`. The request fingerprint
includes the exact pending storage files and their saved/active SHA1 values;
storage coordinates and hashes are not returned as the public activation
status. Requests and lifecycle events are stored outside the infobase in the
local SQLite database selected by `ONEC_ADAPTER_STATE_DB`, in
`configuration_activation_requests` and
`configuration_activation_events`. The legacy JSON path selected by
`ONEC_CONFIGURATION_ACTIVATION_STATE_FILE` is imported once and then remains
read-only.
- `configuration.activation.execute` currently accepts only `mode=debug` and
requires `confirm_activation=true` plus the exact request id. It repeats the
live SQL read and rejects the request if it expired, the base differs, the
pending state disappeared, or any fingerprinted file changed. A successful
result is `debug_accepted`; Designer is not started and the active
configuration is not changed. Use
`configuration.activation.request.status` to inspect the adapter-local
request state.
- `configuration.activation.request.cancel` requires `confirm_cancel=true` and
records a lifecycle event for the exact request. Cancellation is idempotent
and has no 1C side effect. `configuration.activation.audit` returns a bounded
base-scoped list of request states and events without exposing the internal
per-file fingerprint evidence.
- `configuration.activation.capabilities` reports only boolean/configuration
readiness: runner kind, presence of a Designer path and infobase selector,
external-1C enable flag, and supported workflow gates. It never returns the
executable path, runner URL, infobase selector, users, passwords, or tokens.
The base layer reports documented `/UpdateDBCfg` as `debug_only`; extension
activation reports `manual_only` until a verified platform command is
implemented.
- `configuration.activation.bridge.probe` performs an explicit debug-only
readiness call. For a local runner it checks that the configured Designer
executable exists and exactly one infobase selector is present. For an HTTP
runner it calls `/configuration/activation/debug` using the existing runner
token configuration. Both paths return only booleans and runner kind:
Designer is not started, credential values are not read by the local probe,
and paths, URLs, selectors, users, and secret names are not returned.
- `configuration.activation.execute` accepts optional `bridge_debug=true`.
After all request, expiry, confirmation, live-SQL, and fingerprint checks
pass, the adapter sends only `base_id`, semantic layer, request id, and the
64-hex fingerprint to the debug runner. The runner must return a matching
request/fingerprint plus a 64-hex receipt. A missing, mismatched, or
not-ready receipt blocks acceptance. A valid receipt records the
`bridge_debug_accepted` lifecycle event; it still does not start Designer or
change the active configuration.
- `configuration.activation.verify` closes the manual activation loop for an
exact request. It repeats the live SQL comparison with no cache. The result
is `not_activated` when the original fingerprint is still pending,
`changed_since_request` when pending files differ from the confirmed
fingerprint, and `verified_up_to_date` only when saved and active layers
align. SQL alignment does not prove that Designer performed activation—it
can also result from discarding or replacing saved changes—so the response
reports `activation_proven=false`.
- `metadata.saved_state.changes.list` is the read-only pending-change overview
across the base and extension saved-state layers. Use the semantic
`layer=base_saved_state|extension_saved_state` filter when only one layer is
needed; the low-level `table` filter is retained for compatibility. Its
default response is name-first: object/form/module context is resolved
automatically, layer names are semantic, and SQL tables/files, GUIDs, hashes, module refs, concrete diff
selectors, low-level actions, and SQL-specific freshness vocabulary are
hidden. Unresolved changes remain in the
counts and are marked `context_unresolved`. Use `include_storage=true` for
the previous per-file diagnostic view with concrete `diff_selector` links.
`include_unchanged=true` also includes unchanged entries. The freshness of
the pending-change list remains live SQL verified, while context is
explanatory metadata. Pass
`group_by_context=true` to also return compact `groups` keyed by resolved
form/module/object context; grouping uses the same best-effort context
enrichment and falls back to per-file groups when context cannot be resolved.
In diagnostic storage mode each group includes compact `selectors`: per-file
`diff` selectors, plus
`module_refs` and `write_plan_targets` when the resolved module context
exposes them. Groups also include `next_actions`, derived from those
selectors, for safe follow-up calls such as inspecting a diff, reading a
module through `code.read state=working`, or running read-only
`metadata.write.preflight`. `action_summary` counts those follow-up calls by
kind/method, and `recommended_next_action` points to the first safe action,
preferring diff inspection before module reads and write preflight checks.
When `group_by_context=true`, the root response also includes an aggregated
`action_summary` and root `recommended_next_action` with the selected group
identity plus the action payload.
- Saved-state form module writes refresh the SQL-derived code index for the
embedded module. Cache/vector results remain acceleration only; verified
answers still require `payload_sha1` and `text_sha1` revalidation against
current SQL.
## Code Index And Vector Candidates
SQL remains the source of truth. Code cache and vector search are acceleration
layers only.
Freshness statuses:
- `live_sql_verified`: code was read directly from SQL for the answer;
- `cache_hit_verified`: cache candidate was rechecked against current SQL
`payload_sha1` and `text_sha1`;
- `cache_hit_stale`: cache candidate exists, but current SQL no longer matches;
- `cache_refreshed_from_sql`: a stale cache row was rebuilt from current SQL
and will be reranked before it can be returned;
- `vector_candidate_unverified`: vector result is only a retrieval candidate.
- `dirty_with_live_fallback`: local coverage is incomplete, so the response
includes a direct live-SQL search for newly added code.
RPC methods:
```json
{
"method": "metadata.code_index.build",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCAS",
"prefix": "<optional file prefix>",
"max_items": 500,
"include_vectors": true
}
}
```
- `metadata.code_index.status`: reports cache/module/vector chunk counts,
pending outbox events, overlay tombstones, and the local snapshot token;
- `metadata.code_index.search`: strict lexical search over cached BSL. Strict
mode is the default: it overfetches, verifies against live SQL, refreshes and
discards stale rows, and switches to live SQL while the index is dirty;
- `metadata.code_index.verify`: verifies one `module_ref` against live SQL;
- `metadata.code_index.refresh_changed`: verifies search candidates and refreshes
stale modules from SQL;
- `metadata.code_index.sync_pending`: processes exact dirty/outbox targets after
saved-state writes;
- `metadata.code_index.poll_changes`: detects Configurator/external changes.
Saved tables are checked by default; use `include_active=true` for a less
frequent active-configuration scan;
- `metadata.code_vector.pending`: returns current BSL chunks that still need an
embedding for a requested model, with `chunk_id` and `text_sha1`
preconditions. Optional `chunk_kinds=["routine"]` and `max_text_chars`
support fast incremental passes without falsely marking skipped long chunks
as embedded;
- `metadata.code_vector.embedding.upsert`: stores an external embedding only
while those preconditions still match. Changed or removed chunks return
`conflict`;
- `metadata.code_vector.search`: hybrid lexical/vector search over cached
module/routine chunks. It overfetches, verifies live SQL, reranks after stale
refreshes, suppresses active rows shadowed by saved state, and returns
name-first `object_ref`/`object_selector` fields.
If older global index rows have empty owners, run
`metadata.module_owner_cache.backfill` page by page. Search also performs a
cheap local owner lookup for top candidates. For base `Config`/`ConfigSave`
modules whose part name starts with a GUID, the adapter resolves that GUID
against current metadata, requires an exact identity match, and persists the
verified public owner. It never launches a configuration-wide owner scan on
the hot search path.
For active extension `ConfigCAS` modules, the adapter follows the current
extension manifest from the exact CAS content hash to the owning descriptor,
decodes its public kind/name, and returns the extension name/GUID in both
`owner.extension` and `object_selector`. The manifest relation and descriptor
are cached locally only after this current-SQL resolution. Hashes are never
presented as object names.
`strict=true` and `verify=true` are the safe defaults. `strict=false` is a
diagnostic/candidate mode and must not drive programming changes.
The adapter keeps revision, dirty/outbox, tombstone, and vector data in the
local adapter SQLite database. It does not add project tables or settings to
the 1C SQL database.
External embeddings are optional. The worker supports deterministic local
hashing for tests and any OpenAI-compatible embedding endpoint:
```powershell
python scripts\embed_1c_code_vectors.py `
--base-id upo_test `
--embedding-provider openai-compatible `
--embedding-model <code-embedding-model> `
--embedding-base-url http://<embedding-host>:<port> `
--json
python scripts\search_1c_code_vectors.py "где рассчитывается налог" `
--base-id upo_test `
--embedding-provider openai-compatible `
--embedding-model <code-embedding-model> `
--embedding-base-url http://<embedding-host>:<port> `
--embed-pending `
--json
```
API keys are read only from the configured environment variable and are not
written to SQLite, responses, or project files. The embedding model label and
vector dimensions are stored so vectors from different models cannot be mixed.
For Matryoshka-capable OpenAI-compatible models the code worker includes the
requested dimension in the cache label (for example `@d384`), slices a longer
response deterministically, and normalizes the stored vector again.
Operational modes:
- `fast`: strict cache search plus SQL hash verification;
- `live`: direct SQL search/read, slower but authoritative;
- `background_refresh`: intended for long cache warming jobs.
Never apply code changes from cache or vector output alone. Use the returned
`read_selector` after freshness is `cache_hit_verified`, then run the normal
live write preflight. A non-null snapshot token identifies a clean local index;
it is not a native 1C repository lock.
## Saved-State Form Search And Write Target Resolve
RPC methods:
```json
{
"method": "metadata.saved_state.forms.search",
"payload": {
"base_id": "<base-id>",
"tables": ["ConfigCASSave", "ConfigSave"],
"element": "КомандаПример1",
"scan_limit": 1000
}
}
```
```json
{
"method": "metadata.form.write_target.resolve",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCASSave",
"form": "ТестНастройки",
"command": "КомандаПример1",
"property": "Заголовок",
"value": "ПРОВЕРКА"
}
}
```
```json
{
"method": "metadata.form.write_target.verify",
"payload": {
"base_id": "<base-id>",
"extension": "<extension-name>",
"form": "ТестНастройки",
"command": "КомандаПример1",
"property": "Заголовок"
}
}
```
Output schemas:
```text
onec_saved_state_form_search.v1
onec_form_write_target_resolution.v1
```
Purpose:
- search saved-state form payloads without running the heavyweight global
definition scan;
- resolve an agent-facing write intent into `table`, `file_name`, decoded
section (`items`, `commands`, `attributes`, `attribute_fields`, `tables`, or
`command_bars`), exact path, current value, and writable properties;
- prefer selector intent when names overlap: `element`/`element_name` search
form items first, then commands; `command` searches commands; `attribute`
searches form attributes and value-table fields. Use `element_path`/`path`
or `element_id`/`id` for strict physical disambiguation;
- return both the legacy `target`/`effective_target` fields and the
source-aware `display`, `write_target`, and `alternatives` fields when the
visible property is inherited. For example, an empty element caption may be
resolved to the linked form command caption;
- use the form property registry for aliases and verification rules. Current
registry covers `id`, `name`, `title`/`Заголовок`, `path_to_data`/
`ПутьКДанным`, `visible`/`Видимость`, `enabled`/`Доступность`, and
`read_only`/`ТолькоПросмотр`, plus form layout/button properties such as
`Использование`, `Группа`, `Вид`, `Отображение`, `ПоложениеЗаголовка`,
`ПоложениеВКоманднойПанели`, `УникальностьКоманды`, `ЦветФона`,
`ЦветТекста`, and `ЦветРамки`;
- refuse to silently create a local title override when a caption is derived
from `ПутьКДанным`. Pass `source=local_override` on the edit when a local
form-element override is intentional;
- resolve `ПутьКДанным` captions by source:
if the path points to a form attribute, write the form attribute title; if it
points to a tabular form attribute field such as `ТЗ.К1`, write that field
title; if it points to an object/configuration attribute such as
`Объект.<Реквизит>`, write the local form element title instead;
- return candidate diagnostics when a selector is missing or ambiguous;
- produce a human-readable semantic diff such as
`КомандаПример1.Заголовок: Пример1 -> ПРОВЕРКА`.
## Saved-State Form Write Matrix
RPC methods:
```json
{
"method": "metadata.form.write_matrix.build",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCASSave",
"file_name": "<form-file-name>"
}
}
```
```json
{
"method": "metadata.form.write_matrix.smoke",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCASSave",
"file_name": "<form-file-name>",
"allow_sql_saved_state_apply": true,
"allow_sql_saved_state_rollback": true,
"max_candidates": 10,
"learning_id": "write-matrix-case"
}
}
```
Purpose:
- enumerate all decoded writable scalar form properties that the adapter can
read from saved-state form payloads;
- resolve each property through the same source-aware routing used by
`metadata.write`, including command captions, form attribute captions, and
tabular form attribute field captions;
- classify each entry as `can_smoke=true` or return a reason such as
`identity_or_binding_property`, `enum_values_unknown`, or
`empty_local_string_requires_codec_probe`;
- run `can_smoke` entries through `apply_and_rollback` and record verified
routes in a write-learning report when `learning_id` is provided.
## Routine Override Resolution
RPC method:
```text
metadata.resolve_overrides
```
Purpose:
- build a routine chain for a concrete object and method name across base and
extension modules;
- include modules of forms owned by the selected object, including extension
objects resolved from a public `ref`/`kind`/`name` without requiring an
extension GUID or CAS key;
- apply the same source policy as code reads: `state=working` prefers the saved
form-module counterpart with active fallback, `state=save` is saved-only,
`state=active` is active-only, and `state=both` can report both versions;
- mark every chain link with `activation_state=active|saved_state`, so a saved
routine is never mistaken for already applied runtime code;
- return public read selectors for every found routine without exposing storage
ids by default;
- expose `chain[].extension_action` for each routine link. For base
configuration links this is `operation_class=base_definition`;
- for extension links, normalize known action evidence into
`insert_before`, `insert_after`, `replace`, or `replace_with_control`;
- classify an unannotated routine of an object defined by the extension itself
as `extension_definition`; it is not an unresolved interception of a base
routine and therefore does not trigger the unknown-action write guard;
- when a routine is found in an extension but the action metadata is not yet
resolved, return `extension_action.status=unknown` and
`operation_class=unknown_extension_action`. The agent must not treat this as
an ordinary replace;
- for `replace_with_control`, carry `requires_control_fragment=true`; write
planning still requires the controlled base fragment, `controlled_fragment`,
or `expected_old_contains` before apply.
- return `write_plan_evidence`, a ready fragment for `metadata.write.plan`
containing `target.kind=module`, `routine_name`, object selector fields, and
`target.extension_action` when available;
- include `write_plan_evidence.next_resolution.method` and
`write_plan_evidence.next_resolution.params` for
`metadata.saved_state.modules.search`, so the agent has the next safe lookup
for the module. The follow-up uses `ref` or `kind/name` and the semantic
`layer=base_saved_state|extension_saved_state`; it does not expose
`owner_guid` or SQL table names. The saved-state module search also accepts
the object selector aliases and resolves names to storage identities
internally. With the explicit diagnostic
`include_storage=true` option, its matching streams return
`write_plan_target` with `module_ref`, `file_name`, `stream_index`, and
`expected_sha1` for the concrete `metadata.write.plan` target. This override
evidence itself is not a concrete saved-state write route.
- callers can compose `write_plan_evidence.target` with a returned
`streams[].write_plan_target`, add the required operation guards, and pass the
result to `metadata.write.plan`; the accepted plan must route to
`metadata.module.write_apply` without inventing storage field names.
This method is read-only evidence for planning. It tells the agent what must be
known before calling `metadata.write.plan`; it does not select a concrete saved
state route by itself.
## Metadata Write
RPC method:
```json
{
"method": "metadata.write",
"payload": {
"base_id": "<base-id>",
"target": {
"kind": "form",
"table": "ConfigCASSave",
"form": "ТестНастройки",
"element": "КомандаПример1"
},
"mode": "plan",
"edits": [
{"property": "Заголовок", "value": "ПРОВЕРКА"}
]
}
}
```
Output schema:
```text
onec_metadata_write.v1
```
Standard object identity properties use the same high-level method and public
1C selector:
```json
{
"method": "metadata.write",
"payload": {
"base_id": "<base-id>",
"target": {
"area": "object",
"kind": "Catalog",
"name": "Номенклатура",
"property": "synonym"
},
"value": "Номенклатура товаров",
"expected_old": "Товары",
"mode": "plan"
}
}
```
This route delegates to `metadata.object.property.write`. It resolves the
object GUID and exact saved-state tree path internally, supports only existing
`synonym` locales and scalar `comment`, and preserves the original payload
format. Apply modes retain SHA1/semantic preconditions, backup, readback
verification, and rollback. Object rename and structural collection edits are
not part of this route.
An existing child metadata identity uses the same method:
```json
{
"method": "metadata.object.property.write",
"payload": {
"base_id": "<base-id>",
"member_ref": "Catalog.Номенклатура.Attribute.Артикул",
"property": "comment",
"value": "Код товара поставщика",
"allow_saved_state_write": true,
"execution_mode": "plan"
}
}
```
`member_kind` + `member_name` is also accepted. If the same child name occurs
in several collections, callers must provide the full `member_ref`; the
adapter returns `ambiguous` instead of choosing a GUID. Supported existing
member categories are `Attribute`, `TabularSection`, `Dimension`, and
`Resource`, including Russian aliases.
Adding one requisite uses a separate clone-based method:
```json
{
"method": "metadata.object.member.add",
"payload": {
"base_id": "<base-id>",
"template_member_ref": "Catalog.Номенклатура.Attribute.Артикул",
"new_member_name": "КодПоставщика",
"new_member_synonym": "Код поставщика",
"allow_saved_state_write": true,
"execution_mode": "plan"
}
}
```
The adapter requires an existing `Attribute` template from the same collection,
generates a deterministic GUID internally, rejects duplicate names, clones the
template type/settings, and appends the cloned record to the same declared
collection. The proposal verifies both the appended node and updated declared
count. Apply/verify/rollback use the normal saved-state gates and backup.
For a tabular-section column, use the complete nested template path:
```text
Document.АвансовыйОтчет.TabularSection.Запасы.Attribute.Номенклатура
```
Name uniqueness and the deterministic GUID seed are scoped to that tabular
section, so identical column names in other table parts do not conflict.
Scheduled-job schedule planning uses the same method and a public 1C reference:
```json
{
"method": "metadata.write",
"payload": {
"base_id": "<base-id>",
"target": {
"kind": "schedule",
"ref": "РегламентныеЗадания.ОбменДанными"
},
"schedule": {
"begin_time": "09:00:00",
"week_days": [1, 2, 3, 4, 5]
},
"allow_saved_state_write": true,
"mode": "plan"
}
}
```
This route returns `onec_scheduled_job_schedule_write.v1`, resolves the object
name to its GUID internally, and targets only `<guid>.0` in `ConfigSave`.
Purpose:
- provide one agent-facing write entry point;
- reject write requests that do not resolve to a full 1C path, explicit layer,
or concrete saved-state/module reference;
- use the same planning shape as `metadata.write.plan` before any apply mode;
- return a blocked `metadata.write.plan` result instead of applying when the
target is only an effective `canonical_path` without origin/layer evidence or
a concrete saved-state/module reference;
- include the blocked plan's `apply_payload_hint` and `next_resolution` in the
`metadata.write` response when a full form/module path can be parsed, so the
agent can resolve the saved-state target without treating the effective view
as writable;
- after the agent provides a concrete saved-state `file_name` or `module_ref`
for a parsed full path, merge missing selector fields from the same
`apply_payload_hint` into the apply payload, for example `form`/`element` or
`routine_name`, while preserving explicit user payload values;
- preserve the concrete reference field type in write planning and apply hints:
`module_ref`, `module_id`, `file_name`, and `form_guid` must not be collapsed
into a generic string or rewritten as another selector field;
- reject incompatible concrete reference fields for the selected target kind
with `concrete_reference_kind_mismatch`, for example `form_guid` on
`target_kind=module` or `module_ref` on `target_kind=form`;
- do not call lower-level apply methods when the same read-only
`metadata.write.plan` reports `allowed=false`; return `status=blocked`,
`error=write_plan_blocked`, the blocking `problems`, and the plan instead;
- require `metadata.form.element.write_apply` and
`metadata.module.write_apply` to run the same read-only plan gate before SQL
apply, even when they are called directly instead of through
`metadata.write`;
- v1 routes `target.kind=form` to
`metadata.form.element.write_apply`;
- v1 routes `target.area=object` to
`metadata.object.property.write` for `synonym` and `comment`;
- v1 routes `target.area=object` with `operation=add_attribute` to
`metadata.object.member.add`;
- v1 routes `target.kind=schedule` to the named scheduled-job schedule writer;
scalar schedule fields and structural `week_days`/`months` resize are
supported through a verified full schedule-tree replacement;
- v1 routes saved-state form payload container module refs without `#stream`
to the embedded form payload writer when `routine_name` and `routine_text`
identify a single routine edit; this path preserves existing leading BSL
directives such as `&НаКлиенте` if the replacement text omits them;
- treat saved-state preparation as an adapter concern: when `metadata.write`
receives a current active form/module target from `Config` or `ConfigCAS`,
`plan` returns a `metadata.saved_state.prepare` plan, while apply modes with
`allow_sql_saved_state_apply=true` prepare `ConfigSave`/`ConfigCASSave`
internally and continue against that save layer;
- preserve the same gates as the lower-level form runner:
`plan`, `apply`, `apply_and_rollback`, explicit SQL apply/rollback flags,
sha1 preconditions, backup, and semantic verification;
- keep remaining writers behind explicit target routing instead of ad-hoc
direct SQL methods.
## Metadata Write Preflight
RPC method:
```json
{
"method": "metadata.write.preflight",
"payload": {
"base_id": "<base-id>",
"target": {
"kind": "module",
"module_ref": "ConfigCASSave:<file-name>#stream:0"
},
"intent": {
"operation": "replace_with_control",
"control_fragment": "<current-fragment>",
"new": "<new-fragment>"
}
}
}
```
Output schema:
```text
onec_metadata_write_preflight.v1
```
Purpose:
- provide a read-only check immediately before `metadata.write`;
- combine `metadata.write.plan` with live SQL saved-state verification;
- return `status=ready`, `needs_prepare`, `needs_resolution`, or `blocked`;
- report `saved_state.freshness.status=live_sql_verified` for concrete
saved-state targets verified against SQL;
- never create or modify `ConfigSave`/`ConfigCASSave`;
- let `metadata.write` keep saved-state preparation as an adapter concern:
agents should not ask the user whether to create save rows.
## Metadata Write Plan
RPC method:
```json
{
"method": "metadata.write.plan",
"payload": {
"base_id": "<base-id>",
"target": {
"canonical_path": "Справочник.Контрагенты.Наименование"
},
"intent": {
"operation": "property_change",
"property": "Синоним",
"value": "Контрагент"
},
"preferred_layer": "auto"
}
}
```
Output schema:
```text
onec_metadata_write_plan.v1
```
Purpose:
- resolve the requested change target to a full 1C path or return ambiguity
candidates;
- infer `target_kind` from full path sections when it is not explicit, for
example `...Форма.<FormName>.<Member>` routes as `form` and
`ОбщийМодуль.<Name>.<Routine>` routes as `module`;
- read effective and origin evidence before selecting a write route;
- use `metadata.definition.find` for read-only origin lookup when a
`canonical_path` is provided, returning compact matches, `origin`,
`read_selector`, and `related_selectors` under `origin_lookup`;
- accept public `target.origin` or top-level `origin` from prior
`code.search`, `code.read`, `modules.search`, or `modules.read` results and
normalize it into `origin_lookup.method=provided_origin_evidence` for layer
recommendation without repeating the lookup;
- accept public `target.extension_action`, top-level `extension_action`, or a
single-item `extension_actions` list from `metadata.resolve_overrides`. If
the write intent has no explicit operation, known action evidence may infer
`route.operation_class`; unknown action evidence blocks planning with
`extension_action_unknown`;
- block multi-item `extension_actions` with `extension_action_ambiguous` until
the caller narrows the extension/module/routine context to one concrete
action;
- reject mismatches between explicit module-code operation and extension action
evidence with `extension_action_operation_mismatch`, because extension code
changes must preserve `insert_before`, `insert_after`, `replace`, or
`replace_with_control` semantics;
- return `ambiguous_origin_matches` when origin lookup finds more than one
matching definition, even if all matches are in the same layer; callers must
narrow object/form/module/routine context before apply;
- classify the current owner as base configuration, extension, saved-state
working copy, generated extension source, or read-only reference evidence;
- return `route.recommended_write.write_surface` from origin evidence:
`base_saved_state` for configuration origin, `extension_saved_state` for a
resolved extension origin, `saved_state` for an already concrete saved-state
origin, `blocked_unknown` for unresolved owners, or `blocked_conflict` when
multiple layers match the target;
- normalize `preferred_layer` (`auto`, `base`, `extension`,
`generated_extension_source`, including Russian aliases) and return
`preferred_layer_conflict` when it disagrees with origin-derived
`recommended_write`;
- accept `preferred_extension` as an optional extension name/GUID and return
`preferred_extension_conflict` when it disagrees with the resolved extension
owner;
- select the smallest allowed operation such as `add`, `property_change`,
`insert_before`, `insert_after`, `replace`, `replace_with_control`,
`append_routine`, `upsert_routine`, or `move_form_item`;
- normalize natural operation names into `route.operation_class`, including
Russian phrases such as `вставить до`, `вставить после`, `вместо`, and
`вместо с контролем`;
- return `route.apply_payload_hint` for concrete saved-state module/form
routes, mapping normalized operations and guard fields into the next safe
planner/apply method payload such as `metadata.module.write_apply`;
- include `target.concrete_reference_field` and
`target.concrete_reference_source` when a concrete selector was provided, so
the agent can distinguish `module_ref`, module `file_name`, form `file_name`,
and `form_guid`;
- include selector fields derived from `canonical_path` in
`route.apply_payload_hint`, for example object `kind`/`name`, `form`,
`element`, and `routine_name`;
- mark `route.apply_payload_hint.ready_for_apply_method=true` only when the
hint already has a concrete saved-state/module reference; selector-derived
hints must use `ready_for_apply_method=false` and include `next_resolution`,
for example `metadata.saved_state.modules.search` for modules or
`metadata.form.write_target.resolve` for forms;
- report required guards: current sha1, expected old text, controlled fragment,
extension order, conflict scan, BSL validation, and semantic readback;
- for module operations, block `replace_with_control` unless
`control_fragment`, `controlled_fragment`, or `expected_old_contains` is
present. Plain `old` is still useful replacement evidence, but it is not a
controlled base fragment;
- when optional current-source evidence such as `current_text` or `source_text`
is provided for `replace_with_control`, block stale plans with
`control_fragment_drift` if the controlled fragment no longer matches that
source;
- for module `replace`/`replace_with_control`, require old-code evidence
(`old`, `control_fragment`, `expected_old_contains`, `expected_old_sha1`,
`expected_contains`, or `expected_sha1`) and new code (`new`, `text`, or
`routine_text`);
- for module `insert_before`/`insert_after`, require an anchor through
`anchor`, `before`, `after`, or `expected_contains`;
- return `allowed=false` when the target is effective-only, ambiguous,
active-applied, or missing required extension/control evidence.
The planner is read-only. Apply methods may consume the accepted plan, but must
still enforce the explicit saved-state or extension-source gates.
## Metadata Write Learning
RPC methods:
```text
metadata.write_learning.capture_before
metadata.write_learning.capture_after
metadata.write_learning.diff
metadata.write_learning.infer_rule
```
Purpose:
- support the manual learning loop: capture a saved-state form before a
Designer edit, capture it after the edit, compare decoded writable
properties, and infer a repeatable `metadata.write` payload;
- store learning artifacts under `ONEC_ADAPTER_WRITE_LEARNING_DIR` or
`/data/adapter-write-learning`;
- store decoded targets, writable properties, storage sha1 and byte counts;
raw payload hex is not stored in learning captures;
- keep learning scoped to saved-state form payloads in `ConfigSave` and
`ConfigCASSave`.
Example:
```json
{
"method": "metadata.write_learning.capture_before",
"payload": {
"base_id": "<base-id>",
"learning_id": "case-command-title",
"table": "ConfigCASSave",
"form": "ТестНастройки",
"command": "КомандаПример1"
}
}
```
After a manual Designer edit:
```json
{"method": "metadata.write_learning.capture_after", "payload": {"base_id": "<base-id>", "learning_id": "case-command-title", "table": "ConfigCASSave", "form": "ТестНастройки", "command": "КомандаПример1"}}
```
Then:
```json
{"method": "metadata.write_learning.diff", "payload": {"learning_id": "case-command-title"}}
{"method": "metadata.write_learning.infer_rule", "payload": {"learning_id": "case-command-title"}}
```
## Saved-State Form Element Write Planner
RPC method:
```json
{
"method": "metadata.form.element.write",
"payload": {
"base_id": "<base-id>",
"table": "ConfigSave",
"form_guid": "<form-guid>",
"element": "<form-element-name>",
"allow_saved_state_write": true,
"include_payload": true,
"edits": [
{"property": "title", "value": "Новый заголовок"},
{"property": "Видимость", "value": true},
{"property": "Заголовок", "value": "Локальный заголовок", "source": "local_override"}
]
}
}
```
Output schema:
```text
onec_change_proposal.v1
```
Purpose:
- resolve an agent-facing decoded form element (`element`, `element_id`, or
diagnostic `element_path`) into exact form payload paths;
- build a `changes.propose` review payload for saved-state tables only:
`ConfigSave` or `ConfigCASSave`;
- build form proposals in preserve-format mode: only the selected scalar token
span is patched in the original brace text;
- redirect empty inherited captions to their real display source when known,
such as a linked form command title;
- block non-explicit local caption overrides when the display caption appears
to come from `ПутьКДанным`;
- auto-resolve `file_name` through `metadata.form.write_target.resolve` when a
direct form file selector is not provided;
- include `semantic_diff` and candidate diagnostics for agent review;
- verify semantic readback through the same property registry aliases, so an
edit like `command_bar_location` is checked against
`ПоложениеВКоманднойПанели`;
- require explicit `allow_saved_state_write=true` so write intent is visible in
logs and prompts;
- keep direct SQL updates blocked: `write_mode.sql_write_performed=false`.
## Saved-State Form Element Write Runner
RPC method:
```json
{
"method": "metadata.form.element.write_apply",
"payload": {
"base_id": "<base-id>",
"execution_mode": "apply_and_rollback",
"table": "ConfigSave",
"form_guid": "<form-guid>",
"element": "<form-element-name>",
"allow_sql_saved_state_apply": true,
"allow_sql_saved_state_rollback": true,
"edits": [
{"property": "title", "value": "Новый заголовок"}
]
}
}
```
Output schema:
```text
onec_form_element_write_apply.v1
```
Purpose:
- orchestrate the planner, saved-state apply, semantic verification, and
optional rollback in one adapter call;
- support `execution_mode=plan`, `apply`, `apply_and_verify`, and
`apply_and_rollback`;
- force `include_payload=true` internally for apply modes;
- require explicit SQL apply and rollback gates before touching saved-state
rows.
## Saved-State Apply
RPC method:
```json
{
"method": "storage.saved_state.apply_proposal",
"payload": {
"base_id": "<base-id>",
"allow_sql_saved_state_apply": true,
"proposal": "<full proposal from metadata.form.element.write or changes.propose>"
}
}
```
Output schema:
```text
onec_storage_saved_state_apply.v1
```
Purpose:
- apply a reviewed proposal to `ConfigSave` or `ConfigCASSave`;
- require `proposal.encoded.payload_hex`, so the proposal must be created with
`include_payload=true`;
- verify `proposal.original.sha1` against the current saved-state payload before
writing;
- write backup evidence with rollback payload under
`ONEC_ADAPTER_BACKUP_DIR` or `/data/adapter-apply-backups`;
- run the SQL update inside a transaction and verify readback sha1 after commit;
- when the proposal comes from `metadata.form.element.write`, re-read the form
and verify the edited element property through `metadata.form.decode`;
- v1 only updates payloads stored as one SQL part. Multi-part payloads return
`unsupported_part_layout` until a schema-aware multi-part writer is added.
## Saved-State Rollback
RPC method:
```json
{
"method": "storage.saved_state.rollback",
"payload": {
"base_id": "<base-id>",
"allow_sql_saved_state_rollback": true,
"backup_id": "<backup-id-from-apply>"
}
}
```
Output schema:
```text
onec_storage_saved_state_rollback.v1
```
Purpose:
- load backup evidence by `backup_id` or `backup_path`;
- apply the embedded rollback proposal through the same saved-state apply gate;
- return the nested apply result, including readback and semantic verification
when available.
## Saved-State Backups List
RPC method:
```json
{
"method": "storage.saved_state.backups.list",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCASSave",
"file_name": "<saved-state-form-file>",
"limit": 10,
"diagnostic": true
}
}
```
Output schema:
```text
onec_saved_state_backups.v1
```
Purpose:
- list local apply backups from `ONEC_ADAPTER_BACKUP_DIR` or
`/data/adapter-apply-backups`;
- filter by base, table, and file name;
- return backup ids, source metadata, sha1 and byte counts without returning
rollback payload hex.
## Saved-State Backup Retention
RPC method:
```json
{
"method": "storage.saved_state.backups.prune",
"payload": {
"base_id": "<base-id>",
"table": "ConfigCASSave",
"older_than_days": 30,
"keep_latest": 20,
"limit": 500,
"dry_run": true
}
}
```
The method only inspects adapter-local backup JSON files. It is base-scoped,
defaults to `dry_run=true`, preserves `keep_latest` matching backups, and never
writes the 1C database. Actual deletion additionally requires
`dry_run=false` and `confirm_delete=true`. Backups referenced by
`metadata.write.history` are never selected for deletion. If history lookup is
unavailable for a base, its matching backup files remain protected.
## Kind Smoke
Command:
```text
python scripts/smoke_1c_read_view_kinds.py
--kind InformationRegister
--kind AccumulationRegister
--kind AccountingRegister
...
```
Output schema:
```text
onec_read_view_kind_smoke.v1
```
Purpose:
- select first routed object of each kind from the enriched metadata summary;
- run the full read object view pipeline;
- record success/failure and command tails for regression tracking.
## Current Implemented Schemas
```text
onec_sql_read_projection.v1
onec_sql_read_result.v1
onec_sql_reference_resolution.v1
onec_sql_composite_reference_resolution.v1
onec_sql_composite_value_resolution.v1
onec_bsl_symbol_resolution.v1
onec_enum_presentation_map.v1
onec_object_resolution.v1
onec_object_brief_context.v1
onec_object_context_search.v1
onec_saved_state_object_comparison.v1
onec_saved_state_object_detail.v1
onec_saved_state_object_report.v1
onec_saved_state_object_report_check.v1
onec_saved_state_watch_once.v1
onec_saved_state_watch_once_check.v1
onec_saved_state_watch_run_list.v1
onec_saved_state_watch_run_list_check.v1
onec_saved_state_latest_watch_run.v1
onec_saved_state_latest_watch_run_check.v1
onec_saved_state_object_report_delta.v1
onec_saved_state_object_report_delta_check.v1
onec_saved_state_object_change_list.v1
onec_saved_state_object_change.v1
onec_task_context_plan.v1
onec_task_evidence_bundle.v1
onec_task_change_proposal.v1
onec_change_proposal_safety_check.v1
onec_patch_workspace_creation.v1
onec_patch_workspace_manifest.v1
onec_patch_workspace_integrity.v1
onec_patch_source_freshness.v1
onec_patch_workspace_semantic_validation.v1
onec_bsl_routine_edit.v1
onec_form_command_edit.v1
onec_form_button_edit.v1
onec_form_button_workflow.v1
onec_patch_workspace_diff.v1
onec_patch_bundle.v1
onec_patch_bundle_creation.v1
onec_patch_bundle_check.v1
onec_extension_staging.v1
onec_extension_staging_creation.v1
onec_extension_staging_check.v1
onec_extension_runner_config_check.v1
onec_extension_validation_plan.v1
onec_extension_validation_evidence_manifest.v1
onec_extension_validation_evidence_check.v1
onec_extension_validation_release_check.v1
onec_patch_preflight.v1
onec_structured_metadata_from_resolved_xml.v1
onec_sql_read_view.v1
onec_object_artifacts.v1
onec_object_code_context.v1
onec_module_content.v1
onec_form_context.v1
onec_metadata_write_plan.v1
onec_read_view_kind_smoke.v1
```
## Extension Evidence
Declared metadata targets and physical SQL hits must remain separate.
Example:
```text
declared target: cfg:CatalogRef.Пользователи -> _Reference348
physical hit: _Reference348X1
```
The adapter may select an alternate presentation for convenience, but it must
keep `declared target`, `alternate_hits`, and selected presentation as separate
fields.