14 KiB
1C Extension Layer Plan
Status: active work plan.
This plan defines how the 1C adapter and agent must handle extensions, full 1C paths, effective reads, provenance, and safe writes.
Core Principles
The adapter has two responsibilities that must not be merged:
- return the effective picture that the 1C runtime and Configurator see after applying active extensions;
- keep editor provenance so every change can be routed to the correct layer: base configuration, a concrete extension, or a saved-state working copy.
Agent-facing APIs use 1C names and full paths. GUIDs, SQL table names, CAS keys, and payload offsets are storage evidence, not the everyday language of the agent.
Addressing Model
The default address format is a full semantic 1C path:
<ObjectKind>.<ObjectName>[.<Section>.<Member>...]
Examples:
Справочник.Контрагенты
Справочник.Контрагенты.Наименование
Документ.РеализацияТоваровУслуг.Товары.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Измерения.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Ресурсы.Цена
Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Товары
ОбщийМодуль.ИнтеграцияСCRM.ОтправитьКонтрагента
Short names are input conveniences only. Before analysis or writing, the agent must normalize them to a single full path or return candidate paths when the name is ambiguous.
There are three allowed address levels:
canonical_path: full 1C path, safe for reads and write planning;context_path: shortened path valid only inside a known object, form, module, tabular section, or routine;local_name: local BSL symbol or local form item name, never enough for a cross-object write by itself.
The adapter must keep metadata path resolution separate from code symbol
resolution. In BSL, Номенклатура.ЕдИзмерения.Код may start from a variable,
form attribute, object attribute, tabular-section column, query field, or
procedure parameter. It must not be silently treated as
Справочник.Номенклатура.
Layer Views
Every read API that can be affected by extensions should support these views:
base: only the main configuration;extension: only one selected extension;effective: the runtime/configurator picture after applying active extensions;origin: provenance of effective members and code fragments;diff: semantic differences between base and one or more extensions.
The effective view is the default for agent investigation. It is incomplete for writing unless paired with origin and write-target evidence.
Extension Provenance
For every metadata object, member, form, module, routine, command, and event handler, responses should expose:
canonical_path;presentationand synonym when known;created_in;modified_by;effective_owner;active_extensions;extension_order;conflicts;storage_evidencefor debug/expert mode.
Extension changes must be classified semantically:
- object added by extension;
- base object adopted/extended by extension;
- attribute/tabular section/form/command/event added;
- property changed;
- module added;
- routine added;
- code inserted before;
- code inserted after;
- code replaced;
- code replaced with control.
For replace_with_control, the adapter must expose the controlled base
fragment and report whether it still matches the current base/effective source.
Write Planning
Writes must start with a plan. The agent may read effective text, but must not write effective text directly.
The write planner must answer:
- what full path or symbol is being changed;
- what layer owns the current effective element;
- which layer is the correct write target;
- whether the target is base saved state, extension saved state, generated extension source, or read-only reference evidence;
- which operation is allowed: add, property change, insert before, insert after, replace, replace with control, append routine, upsert routine, move form item;
- which guards are required: sha1, controlled fragment, expected old text, syntax check, extension order, conflict scan;
- which follow-up reads and validation steps must be run.
The first production-safe write path remains extension-first:
generate extension source
-> validate in 1C tooling
-> package extension
-> load into disposable base
-> run smoke tests
-> produce human approval diff
Direct active configuration writes remain forbidden.
Agent Workflow
For concrete 1C tasks, the agent should follow this sequence:
- Parse the user request and extract likely full paths, short names, and local symbols.
- Resolve all metadata paths through the adapter.
- Read effective context for the selected objects.
- Read origin/layer evidence before drawing conclusions about ownership.
- For BSL expressions, resolve local symbols inside the concrete module, routine, form, or query context.
- If a change is needed, build a write plan before generating or applying a patch.
- Apply only through allowed saved-state, patch-workspace, or extension-source routes.
- Re-read effective and origin views.
- Run semantic diff, BSL syntax checks, saved-state checks, and extension conflict checks.
- Report results to the user in full 1C paths, hiding storage ids unless the user asks for expert evidence.
Work Plan
- Finalize the full-path contract in adapter docs and schemas.
- Extend the resolver model to return
canonical_path,context_path, ambiguity candidates, and path-kind diagnostics. - Add a code symbol resolver that works inside a selected module/routine/form context and distinguishes variables from metadata paths.
- Extend object, form, and module reads with consistent origin fields.
- Add an extension layer inventory that reports active extensions, order, adopted base objects, added objects, and conflicts.
- Add routine-level extension action evidence: before, after, replace, and replace with control.
- Add a read-only write planner that chooses base saved state, extension saved state, or generated extension source without applying changes.
- Wire the planner into
metadata.writeso writes without a resolved full-path target and layer decision are rejected. - Add smoke tests for ambiguous short names, extension-added attributes, extension-overridden routines, and replace-with-control drift.
- Add eval cases so the agent learns to answer with full paths and to refuse unsafe direct effective-text writes.
First Implementation Slice
The first executable slice should be read-only:
- update
resolve_1c_fact.pyoutput to include canonical path metadata; - add path ambiguity tests for object member paths;
- add origin fields to module/routine reads where extension overlays already exist;
- document a proposed
metadata.write.planshape before implementing apply behavior.
Current progress:
resolve_1c_fact.pyreturnscanonical_path,path_kind, and tabular sectioncontext_pathfor verified object/member facts.metadata.write.planvalidates full 1C paths and concrete saved-state/module references without applying changes.metadata.write.planinfers form/module write intent from canonical path sections such asФорма.<FormName>andОбщийМодуль.<Name>.<Routine>.metadata.write.plancan callmetadata.definition.findfor compactorigin_lookupevidence.metadata.write.planreportsambiguous_origin_matcheswhen a full path still resolves to multiple definitions, including same-layer ambiguity such as object member versus form member.metadata.write.planrecommendsbase_saved_state,extension_saved_state,saved_state,blocked_unknown, orblocked_conflictfrom origin evidence.metadata.write.plannormalizespreferred_layerand reportspreferred_layer_conflictwhen a requested base/extension target disagrees with the origin-derived write recommendation.metadata.write.planacceptspreferred_extensionand reportspreferred_extension_conflictwhen the requested extension name/GUID differs from the resolved extension owner.metadata.write.planvalidates module-code preconditions forreplace_with_control,replace, andinsert_before/insert_afterbefore allowing even saved-state plans.metadata.write.plannormalizes Russian and English operation names into stableoperation_classvalues such asinsert_before,insert_after,replace, andreplace_with_control.metadata.write.planreturnsroute.apply_payload_hintfor concrete saved-state module/form routes, so an agent can carry the validated guards intometadata.module.write_applyor form write planning without inventing field names.metadata.write.planalso carries selector fields inferred fromcanonical_pathintoroute.apply_payload_hint, includingkind,name,form,element, androutine_namewhen known.metadata.write.planmarks selector-only module/form hints asready_for_apply_method=falseand returnsnext_resolutionpointing to the required saved-state target resolver before apply methods can be called.metadata.writeblocks direct writes to effectivecanonical_pathtargets without a concrete saved-state/module route.- Blocked
metadata.writeresponses now surface the plan'sapply_payload_hintandnext_resolutionfor parsed form/module paths, keeping the next safe resolver visible without allowing direct writes to the effective view. - When a concrete saved-state form file or module stream is later provided with
that same full path,
metadata.writemerges missing selector fields from the plan hint into the low-level apply payload, such asform,element, androutine_name. - Concrete references now keep their field identity in write planning and
hints:
module_ref,module_id,file_name, andform_guidare not collapsed into each other. - Write planning rejects incompatible concrete references with
concrete_reference_kind_mismatch, so a form selector cannot be used as a module route or the other way around. resolve_1c_bsl_symbol.pyadds the first conservative code-symbol resolver: full paths such asСправочник.Номенклатура.Артикулresolve as metadata, context-proven object-module fields resolve as metadata members, but routine parameters, local variables, and short object names stay BSL symbols until proven otherwise.- The live adapter now exposes the same conservative resolver as
code.symbol.resolve, backed bymodules.read,metadata.definition.find, andmetadata.object.attributes. check_1c_code_symbol_contract.pyverifies the public adapter method throughcall_method, including thatcanonical_path,context_path, andsafe_as_metadata_pathsurvive public-result sanitizing.modules.readnow returns fallback publicoriginevidence from the storage table for direct module references: applied configuration, saved state, or unresolved CAS reference that requires owner resolution before write planning.check_1c_module_origin_contract.pyverifies that publicmodules.readandcode.readresponses keep this origin evidence visible withoutinclude_storage=true.code.searchitems now preserveoriginfrommodules.search, so the agent can see provenance before selecting aread_selectorforcode.read.metadata.write.plannow acceptstarget.origin/originfrom those prior read/search results and converts it toprovided_origin_evidence, preserving layer recommendation while still requiring a concrete write route before apply.metadata.resolve_overridesnow exposesextension_actionper routine link: known evidence is normalized toinsert_before,insert_after,replace, orreplace_with_control; unresolved extension routine actions are reported asunknown_extension_actionso the agent does not silently treat them as a plain replace.metadata.write.plannow accepts thatextension_actionevidence directly: known actions can infer the module operation when the user did not specify one, unknown actions block planning, and explicit operation/action mismatches are rejected before any saved-state apply route can run.- Multi-item
extension_actionsfrom an override chain now block write planning asextension_action_ambiguous; the agent must narrow to one extension/module action before generating a patch. metadata.resolve_overridesnow returnswrite_plan_evidence, a readymetadata.write.planfragment carrying the routine name, object selector fields,target.extension_action, andnext_resolution.paramsformetadata.saved_state.modules.search; saved-state module search now resolves publicobject_type/object_nameselectors to owner GUIDs when possible. This reduces agent-side field translation while still requiring a concrete saved-state module route.metadata.saved_state.modules.searchnow returnsstreams[].write_plan_target, a concrete module target withmodule_ref,file_name,stream_index, andexpected_sha1for the nextmetadata.write.plancall.- The OpenAPI contract now exposes the same write-plan response fields: concrete reference identity, apply payload hints, next resolution, and blocked high-level write responses.
metadata.writenow refuses to call low-level apply methods when the corresponding read-only plan is blocked, for examplereplace_with_controlwithout a control fragment.- Direct saved-state form/module apply methods now run the same
metadata.write.plangate before SQL apply, so low-level callers cannot bypass blocked guard checks. metadata.write.planblocksreplace_with_controlascontrol_fragment_driftwhen optional current-source evidence is supplied and the controlled fragment no longer matches that source.