Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .agents/skills/flext-law/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ Read those skills and root `AGENTS.md`; this file adds only FLEXT domain law.
contract. Never add a replacement toggle or a guard for retired inputs. Agents never
add `WHAT=` or `PROJECT=` to setup, generation, repair, formatting, checking, or
testing.
- Generators emit only what is declared (ADR-018, rule
`~/agents/rules/flext/generator-declarations.md`): a facade letter belongs to the
module that declares it in its explicit `__all__`; an `__init__.py` propagates and
never declares; internal tiers (`tests/`, `examples/`, `scripts/`, any root folder
with Python) are detected, inherit by class MRO and declare their own letter; `src/`
is public, the rest internal. No filename→letter table, closed folder list,
advisory-gate list, single-file guard or validator bypass exists; a derivation
replaces each, and the permission that tolerated a hack dies in the same commit.
Every module is one nested class with nothing loose; the existing rules for that are
`error`. Exceptions exist only by explicit operator authorization, one bead each.
- Structural rewires run through `make mod`. Its canonical FLEXT engine composes
`ast-grep` rewrites, Rope semantic refactors, and real `pyright-langserver`
diagnostics before the fixed point is accepted. Repetitive manual call-site editing is
Expand Down
101 changes: 101 additions & 0 deletions docs/architecture/adr/018-generator-declarations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# ADR-018 — Generator Declarations Law

<!-- TOC START -->

- [Context](#context)
- [Decision](#decision)
- [Consequences](#consequences)
- [Verification contract](#verification-contract)

<!-- TOC END -->

- **Status:** ACCEPTED — operator law 2026-09-20; implementation phased under `flext-0in0k`
- **Date:** 2026-09-20
- **Target line:** FLEXT `0.12.0-dev`, forward baseline `0.13.0`
- **Scope:** every FLEXT generator, detector and fix (`make gen`, `make mod`, `make fix`,
the namespace validator and its gates) and every consumer of them: the `flext`
workspace and its 31 members, ai-hub, cosmos-main and its apps, cosmos-docgen, invest
and their FLEXT subprojects.
- **Complements:** ADR-010 (standardization via codegen), ADR-014 (family shape + codemod
rules), ADR-017 (parametrized rule surfaces). Supersedes every filename→letter table,
closed folder list and advisory-gate list those ADRs tolerated.
- **Rule owner:** `~/agents/rules/flext/generator-declarations.md` (projected to every
provider). This ADR records the decision; the rule file is the binding text.
- **Tracking:** epic `flext-0in0k` (20 phased beads, each carrying the full rule text);
superseded `flext-exbwv`, `flext-crd1y`, `flext-b3xmn`, `flext-szjre`, `flext-fdoah`,
`flext-s9bxq` (closed, linked); `flext-ssnc7` and `flext-mbowt` linked, kept open for
their unrelated live children.

## Context

The lazy-init and `pyproject.toml` generators accumulated accommodations that decide
behavior from names and hand lists instead of declarations: a filename→letter table
(`NAMESPACE_LAYER_BY_FILE`, five readers), closed folder sets (`ROOT_WRAPPER_SEGMENTS`,
`NON_PUBLIC_LAZY_ROOTS`, `ALL_SCAN_PATTERNS`, `env-dirs`/`test-like-dirs`, a literal
fallback in `namespace_config`), a hardcoded `TEST_RUNTIME_ALIAS_TARGETS`, `ALIAS_NAMES`
used as the list of who exists, hand-declared `root_packages`/`root_modules`, a
single-part package name treated as a public root, an advisory-gate list by name, a
guard for one `services/models.py`, and an `examples/` bypass in the validator. Every
consumer of the generator inherited them. On 2026-09-20 the fleet `make gen` broke
(`flext-infra a43dcf547`) because export discovery accepted any class of a module with
no `__all__` and rendered `from .01_basic_usage import …`.

The operator negotiated the correct contract point by point and ordered it to become a
FLEXT rule generators cannot violate, followed by the extermination of every hack and of
the permission that tolerated it, one by one, at the source.

## Decision

The fourteen points of `generator-declarations.md` are law. In one line each:

1. A facade letter belongs to the module that declares it in its explicit `__all__`.
2. An `__init__.py` propagates; it never declares.
3. The root inherits from the main module; the root `__all__` overrides.
4. Internal tiers are detected from folders with Python; `src/` is public, the rest
internal; no list anywhere.
5. Internal tiers inherit by class MRO and declare their own letter; a subdirectory
declares no short alias.
6. The generator propagates, never compensates; the validator reports.
7. Violations are fixed at the source; recurrence makes a catalog rule with a fixture.
8. Verdict and count derive from one classification; `error` fails, warning does not.
9. Every rule is computed from an existing source and proven fleet-wide before commit.
10. Declaration adjustment is automatic; deriving beats listing; unnecessary lists die.
11. Every module is one nested class; nothing loose, no alias outside `__all__`; the
existing rules become `error`.
12. An exception is a single motivated entry authorized explicitly by the operator.
13. A hack's permission dies in the same commit as the hack.
14. Every module obeys every rule (FLEXT, SOLID, DRY, YAGNI, CA, SSOT, DI); strict
compliance is the dedup mechanism expected to free 60–80% of the code.

Order of execution (operator): law → extermination of lists, manual declarations and
their permissions → generator/detector/fix repair → census by the validator → automatic
correction (`make mod`) → consumers → strict compliance → close. One bead per phase; work
in worktrees on the freshly fetched integration tip; never a rollback; never a manual
mass fix.

## Consequences

- `flext-infra` loses every table and list named in Context; the replacement is one
derivation each (`u.Infra.discover_python_dirs`, the module `__all__`, the class
base, the folder on disk). Their permissions (exclusions, bypasses, advisory lists)
leave in the same commits.
- Every consumer regenerates; the diff is the inventory of hacks it carried. Two
flext-infra forks (`flext-sh@0.12.0-dev`, `datacosmos-br@baseline-20260919`)
converge to one line.
- The namespace validator reports one-nested-class, no-alias and nothing-loose
violations as `error`; the fix derives letter ⇄ base and writes the declaration.
- Measured populations at decision time: 42 internal facades without the letter in
`__all__` (10 repos, 0 in `src/`), 5 letters bound to non-extending classes, 4 dead
example classes, 36 numbered scripts inside packages (12 repos), 8 public + 18 private
reserved names in nested packages, 61 internal inits with divergent shapes.

## Verification contract

- `make gen` exits 0 in 32/32 and a second run has no diff, after every flext-infra
commit of the epic — before the commit is pushed.
- `make mod` twice is idempotent; the validator's counts above reach 0.
- `make check` and `make test` green in 32/32 and in every consumer; no new exclusion.
- Logical LOC measured by the canonical verb before the first commit and after the
last; the delta is recorded on `flext-0in0k`.
- `bd lint --json` clean for every bead of the epic; each closes with SHA, command and
exit code.
3 changes: 3 additions & 0 deletions docs/architecture/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ candidate; acceptance never proves fleet stability.
- [ADR-017: Parametrized Rule Surfaces and the Single Modernize CLI](017-parametrized-rule-surfaces-single-modernize-cli.md)
— **ACCEPTED TARGET** (`make mod` wired; `flext-infra/config/rules/mod/` exists;
distribution/migration acceptance remains unproved)
- [ADR-018: Generator Declarations Law](018-generator-declarations.md) — **ACCEPTED**
(operator law 2026-09-20; rule owner `~/agents/rules/flext/generator-declarations.md`;
phased under `flext-0in0k`)

> **Historical numbering evidence:** the recorded `0.20.0-dev` catalog associates
> ADR-011/012 with the forward line and ADR-012 with worktree transaction performance
Expand Down
6 changes: 1 addition & 5 deletions docs/projects/flext-target-oracle-oic.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ make -C flext-target-oracle-oic test
```text
src/flext_target_oracle_oic/
├── api.py # FlextTargetOracleOicService(FlextMeltanoTargetServiceBase)
<<<<<<< Updated upstream
├── target.py # FlextTargetOracleOic(FlextMeltanoTargetAbstractions)
=======
├── target.py # FlextTargetOracleOic — per-stream OIC sinks
>>>>>>> Stashed changes
├── target.py # FlextTargetOracleOicBaseSink + per-stream OIC sinks (m.Meltano.SingerSinkBase)
├── cli.py # FlextTargetOracleOicCli + main entry point
├── _settings.py # FlextTargetOracleOicSettings + settings singleton
├── config/ # Execution parametrization (YAML)
Expand Down
7 changes: 1 addition & 6 deletions docs/projects/flext-target-oracle-wms.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,8 @@ src/flext_target_oracle_wms/
├── api.py # FlextTargetOracleWmsService(FlextMeltanoTargetServiceBase)
├── cli.py # FlextTargetOracleWmsCli + main entry point
├── _utilities/
<<<<<<< Updated upstream
│ ├── client.py # FlextTargetOracleWmsUtilitiesClient (catalog, streams)
│ ├── helpers.py # FlextTargetOracleWmsUtilitiesHelpers (WMSTableManager, ...)
=======
│ ├── client.py # FlextTargetOracleWmsUtilitiesClient (CatalogManager, StreamProcessor)
│ ├── client.py # FlextTargetOracleWmsUtilitiesClient (catalog, stream, target)
│ ├── helpers.py # FlextTargetOracleWmsUtilitiesHelpers (WMSTableManager, transformers)
>>>>>>> Stashed changes
│ └── service_runtime.py # FlextTargetOracleWmsServiceRuntime — WMS target + sink creation
├── _settings.py # FlextTargetOracleWmsSettings + settings singleton
├── config/ # Execution parametrization (YAML)
Expand Down
38 changes: 8 additions & 30 deletions docs/scripts/gate-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ Canonical implementations in this repository:

Required flags:

<<<<<<< Updated upstream | Flag | Type | Default | Description | |
------------------------- | ------ | ---------- | ----------------------------- | |
`--root <path>` | string | `.` | Repository root to scan | | `--mode baseline\|strict` |
enum | `baseline` | Enforcement level (see Modes) |
| Flag | Type | Default | Description |
| ------------------------- | ------ | ---------- | ----------------------------- |
| `--root <path>` | string | `.` | Repository root to scan |
| `--mode baseline\|strict` | enum | `baseline` | Enforcement level (see Modes) |

Optional flags:

Expand All @@ -86,22 +86,6 @@ Optional flags:
| `--update-baseline` | boolean | `false` | Write current counts as new baseline |
| `--baseline-strategy total\|per_group` | enum | `total` | Baseline comparison method |

======= | Flag | Type | Default | Description | | ------------------- | ------ |
---------- | ----------------------------- | | `--root <path>` | string | `.` |
Repository root to scan | | `--mode baseline\|strict` | enum | `baseline` | Enforcement
level (see Modes) |

Optional flags:

| Flag | Type | Default | Description |
| -------------------------------------- | ------- | ---------------- | ------------------------------------ |
| `--report-file <path>` | string | contract default | Override report output path |
| `--baseline-file <path>` | string | contract default | Override baseline path |
| `--update-baseline` | boolean | `false` | Write current counts as new baseline |
| `--baseline-strategy total\|per_group` | enum | `total` | Baseline comparison method |

> > > > > > > Stashed changes

Validators must also accept `--root` as a positional argument (last arg fallback) for
backward compatibility with existing callers.

Expand All @@ -117,16 +101,10 @@ Required flags:

Optional flags:

<<<<<<< Updated upstream | Flag | Type | Default | Description | |
---------------------- | ------ | ---------------- | --------------------------- | |
`--mode safe\|risky` | enum | `safe` | Fix aggressiveness level | |
`--report-file <path>` | string | contract default | Override report output path |
======= | Flag | Type | Default | Description | | -------------------------- | ------ |
---------------- | --------------------------- | | `--mode safe\|risky` | enum | `safe`
| Fix aggressiveness level | | `--report-file <path>` | string | contract default |
Override report output path |

> > > > > > > Stashed changes
| Flag | Type | Default | Description |
| ---------------------- | ------ | ---------------- | --------------------------- |
| `--mode safe\|risky` | enum | `safe` | Fix aggressiveness level |
| `--report-file <path>` | string | contract default | Override report output path |

A fixer must refuse to run if neither `--dry-run` nor `--apply` is provided (exit 2).

Expand Down
Loading