3401 lines
142 KiB
Markdown
3401 lines
142 KiB
Markdown
# 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 is confirmed as `AppearanceTemplate` XML.
|
||
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.
|