# 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:

```text
<ObjectKind>.<ObjectName>[.<Section>.<Member>...]
```

Examples:

```text
Справочник.Контрагенты
Справочник.Контрагенты.Наименование
Документ.РеализацияТоваровУслуг.Товары.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Измерения.Номенклатура
РегистрСведений.ЦеныНоменклатуры.Ресурсы.Цена
Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента.Товары
ОбщийМодуль.ИнтеграцияС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`;
- `presentation` and synonym when known;
- `created_in`;
- `modified_by`;
- `effective_owner`;
- `active_extensions`;
- `extension_order`;
- `conflicts`;
- `storage_evidence` for 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:

```text
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:

1. Parse the user request and extract likely full paths, short names, and local
   symbols.
2. Resolve all metadata paths through the adapter.
3. Read effective context for the selected objects.
4. Read origin/layer evidence before drawing conclusions about ownership.
5. For BSL expressions, resolve local symbols inside the concrete module,
   routine, form, or query context.
6. If a change is needed, build a write plan before generating or applying a
   patch.
7. Apply only through allowed saved-state, patch-workspace, or extension-source
   routes.
8. Re-read effective and origin views.
9. Run semantic diff, BSL syntax checks, saved-state checks, and extension
   conflict checks.
10. Report results to the user in full 1C paths, hiding storage ids unless the
    user asks for expert evidence.

## Work Plan

1. Finalize the full-path contract in adapter docs and schemas.
2. Extend the resolver model to return `canonical_path`, `context_path`,
   ambiguity candidates, and path-kind diagnostics.
3. Add a code symbol resolver that works inside a selected module/routine/form
   context and distinguishes variables from metadata paths.
4. Extend object, form, and module reads with consistent origin fields.
5. Add an extension layer inventory that reports active extensions, order,
   adopted base objects, added objects, and conflicts.
6. Add routine-level extension action evidence: before, after, replace, and
   replace with control.
7. Add a read-only write planner that chooses base saved state, extension saved
   state, or generated extension source without applying changes.
8. Wire the planner into `metadata.write` so writes without a resolved
   full-path target and layer decision are rejected.
9. Add smoke tests for ambiguous short names, extension-added attributes,
   extension-overridden routines, and replace-with-control drift.
10. 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.py` output 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.plan` shape before implementing apply
  behavior.

Current progress:

- `resolve_1c_fact.py` returns `canonical_path`, `path_kind`, and tabular
  section `context_path` for verified object/member facts.
- `metadata.write.plan` validates full 1C paths and concrete saved-state/module
  references without applying changes.
- `metadata.write.plan` infers form/module write intent from canonical path
  sections such as `Форма.<FormName>` and `ОбщийМодуль.<Name>.<Routine>`.
- `metadata.write.plan` can call `metadata.definition.find` for compact
  `origin_lookup` evidence.
- `metadata.write.plan` reports `ambiguous_origin_matches` when a full path
  still resolves to multiple definitions, including same-layer ambiguity such
  as object member versus form member.
- `metadata.write.plan` recommends `base_saved_state`, `extension_saved_state`,
  `saved_state`, `blocked_unknown`, or `blocked_conflict` from origin evidence.
- `metadata.write.plan` normalizes `preferred_layer` and reports
  `preferred_layer_conflict` when a requested base/extension target disagrees
  with the origin-derived write recommendation.
- `metadata.write.plan` accepts `preferred_extension` and reports
  `preferred_extension_conflict` when the requested extension name/GUID differs
  from the resolved extension owner.
- `metadata.write.plan` validates module-code preconditions for
  `replace_with_control`, `replace`, and `insert_before`/`insert_after` before
  allowing even saved-state plans.
- `metadata.write.plan` normalizes Russian and English operation names into
  stable `operation_class` values such as `insert_before`, `insert_after`,
  `replace`, and `replace_with_control`.
- `metadata.write.plan` returns `route.apply_payload_hint` for concrete
  saved-state module/form routes, so an agent can carry the validated guards
  into `metadata.module.write_apply` or form write planning without inventing
  field names.
- `metadata.write.plan` also carries selector fields inferred from
  `canonical_path` into `route.apply_payload_hint`, including `kind`, `name`,
  `form`, `element`, and `routine_name` when known.
- `metadata.write.plan` marks selector-only module/form hints as
  `ready_for_apply_method=false` and returns `next_resolution` pointing to the
  required saved-state target resolver before apply methods can be called.
- `metadata.write` blocks direct writes to effective `canonical_path` targets
  without a concrete saved-state/module route.
- Blocked `metadata.write` responses now surface the plan's `apply_payload_hint`
  and `next_resolution` for 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.write` merges missing selector fields from the
  plan hint into the low-level apply payload, such as `form`, `element`, and
  `routine_name`.
- Concrete references now keep their field identity in write planning and
  hints: `module_ref`, `module_id`, `file_name`, and `form_guid` are 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.py` adds 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 by `modules.read`, `metadata.definition.find`,
  and `metadata.object.attributes`.
- `check_1c_code_symbol_contract.py` verifies the public adapter method through
  `call_method`, including that `canonical_path`, `context_path`, and
  `safe_as_metadata_path` survive public-result sanitizing.
- `modules.read` now returns fallback public `origin` evidence 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.py` verifies that public `modules.read`
  and `code.read` responses keep this origin evidence visible without
  `include_storage=true`.
- `code.search` items now preserve `origin` from `modules.search`, so the
  agent can see provenance before selecting a `read_selector` for `code.read`.
- `metadata.write.plan` now accepts `target.origin`/`origin` from those prior
  read/search results and converts it to `provided_origin_evidence`, preserving
  layer recommendation while still requiring a concrete write route before
  apply.
- `metadata.resolve_overrides` now exposes `extension_action` per routine link:
  known evidence is normalized to `insert_before`, `insert_after`, `replace`,
  or `replace_with_control`; unresolved extension routine actions are reported
  as `unknown_extension_action` so the agent does not silently treat them as a
  plain replace.
- `metadata.write.plan` now accepts that `extension_action` evidence 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_actions` from an override chain now block write
  planning as `extension_action_ambiguous`; the agent must narrow to one
  extension/module action before generating a patch.
- `metadata.resolve_overrides` now returns `write_plan_evidence`, a ready
  `metadata.write.plan` fragment carrying the routine name, object selector
  fields, `target.extension_action`, and `next_resolution.params` for
  `metadata.saved_state.modules.search`; the follow-up uses a public object
  `ref`/`kind`/`name` and semantic saved-state `layer`, while the search
  resolves storage identities internally.
  This reduces agent-side field translation while still requiring a concrete
  saved-state module route.
- With `include_storage=true`, `metadata.saved_state.modules.search` returns
  `streams[].write_plan_target`, a concrete module target with `module_ref`,
  `file_name`, `stream_index`, and `expected_sha1` for the next
  `metadata.write.plan` call.
- 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.write` now refuses to call low-level apply methods when the
  corresponding read-only plan is blocked, for example
  `replace_with_control` without a control fragment.
- Direct saved-state form/module apply methods now run the same
  `metadata.write.plan` gate before SQL apply, so low-level callers cannot
  bypass blocked guard checks.
- `metadata.write.plan` blocks `replace_with_control` as
  `control_fragment_drift` when optional current-source evidence is supplied
  and the controlled fragment no longer matches that source.
