diff --git a/.gitignore b/.gitignore index a17f4aa..04dbb9d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,5 @@ dist/ /site/ /_site/ -# gate evidence (pre-GitHub era): curated records live at tag archive/pre-github; -# raw session captures are local-only +# gate evidence (pre-GitHub era) — local-only, never tracked /gates/ diff --git a/README.md b/README.md index 052b01a..5c49a68 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,6 @@ pip install -e '.[dev]' pytest ``` -## License & history +## License -Licensed under [Apache-2.0](LICENSE). The pre-GitHub PRD, specs, and phase-gate evidence live at -the git tag `archive/pre-github`. \ No newline at end of file +Licensed under [Apache-2.0](LICENSE). \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index bbc2b8c..1926d0e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,6 +29,3 @@ New capabilities and design changes go through [proposals/](../proposals/README.md) and GitHub issues. Docs in this directory describe the **current** system; a proposal that lands updates them in the same PR. - -Pre-GitHub history (the PRD, numbered specs 01–15, and phase-gate evidence for Phases 0–29) is -preserved at the git tag `archive/pre-github`. diff --git a/docs/architecture.md b/docs/architecture.md index c16a344..05c4178 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -105,7 +105,7 @@ guess, not a proof. ``` src/ea_core/ # the deterministic engine + `ea` CLI -tests/ # unit + e2e contract tests (incl. per-gate e2e suites) +tests/ # unit + e2e contract tests (incl. per-feature e2e suites) plugins/ # the two adapter surfaces (ea-claude, ea-antigravity) packs/ # production method packs (open-agile-architecture, # enterprise-architecture, lean-ux, …) diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 01a1048..ca41d6d 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -4,9 +4,7 @@ Short records of the **still-binding** design decisions whose *why* is not obvio reference docs — the constraints a future change must either respect or deliberately revisit (via a [proposal](../../proposals/)). -Historical context: these distill the D1–D41 decision log of the pre-GitHub era PRD. The full -log, the numbered specs, and the phase-gate evidence live in git history at the tag -**`archive/pre-github`**. +Historical context: these distill the D1–D41 decision log of the pre-GitHub era PRD. | # | Decision | |---|---| diff --git a/proposals/0001-ea-show.md b/proposals/0001-ea-show.md index 522d691..64ee280 100644 --- a/proposals/0001-ea-show.md +++ b/proposals/0001-ea-show.md @@ -12,13 +12,13 @@ Agents inspecting a single artifact today either read the whole file from disk o `report`/`validate` output to the purpose. There is no read verb that returns one artifact's front-matter (and body) through the contract, and no way to trim the response to the needed fields — the read-side `--fields` projection (spec 09; spec numbers, like D-numbers, refer to -the archived pre-GitHub record at `archive/pre-github`) covers the record/key-shaped verbs only. +the archived pre-GitHub record) covers the record/key-shaped verbs only. Reading files directly costs tokens (the body rides along even when only one field is needed), bypasses the self-describing not-found contract, and pushes resolution logic (scope fall-through, layering) onto every surface — a per-host duplication P2 exists to prevent. -The gap was deferred deliberately: D28/D29 (at `archive/pre-github`) kept artifact front-matter +The gap was deferred deliberately: D28/D29 kept artifact front-matter out of `graph dependency --fields` because inlining it would either break the purely-subtractive invariant or bloat the default output, and pointed instead at "a purpose-built single-artifact `ea show --fields`, where trimming front-matter is naturally subtractive". The Phase-19 advisory diff --git a/proposals/0002-validate-warning-dead-renames.md b/proposals/0002-validate-warning-dead-renames.md index c225346..0f01abf 100644 --- a/proposals/0002-validate-warning-dead-renames.md +++ b/proposals/0002-validate-warning-dead-renames.md @@ -10,7 +10,7 @@ A manifest `renames:` entry whose `from` names no rule the active set actually renamed is **silently ignored** at materialization. The overlay maps a pack's published rule id to a local -id (`{pack, kind: rule, from, to}`, decision 0007, D38 at `archive/pre-github`); the mapping is +id (`{pack, kind: rule, from, to}`, decision 0007, D38); the mapping is consulted only through `materialize.local_rule` while walking selected methods (`src/ea_core/materialize.py`). An entry that no selected method reaches is never applied and never reported — the closure just doesn't call `local_rule` with that key. diff --git a/tests/e2e/test_archetype_migrate.py b/tests/e2e/test_archetype_migrate.py index 12bcb34..fe470bf 100644 --- a/tests/e2e/test_archetype_migrate.py +++ b/tests/e2e/test_archetype_migrate.py @@ -1,4 +1,4 @@ -"""Phase-7 gate (archived at tag archive/pre-github): write-side — ``ea migrate`` (archived at tag archive/pre-github). +"""Write-side — ``ea migrate``. An existing ``startup-light`` configuration evolves to ``enterprise-heavy`` via a reviewed, confirmed plan that **preserves prior deliberate choices** and **surfaces @@ -29,7 +29,7 @@ ROOT = Path(__file__).resolve().parents[2] MANIFEST = "ea.manifest.yaml" -INDEX = "definitions/index.yaml" # the pack@version integrity lock (Phase 14) +INDEX = "definitions/index.yaml" # the pack@version integrity lock NEW_DEFS = [ "definitions/methods/data-modeling.yaml", "definitions/methods/service-design.yaml", @@ -184,7 +184,7 @@ def test_drift_after_plan_is_refused(repo): def test_migrate_plan_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1).""" + """Identical inputs → byte-identical stdout (P1).""" _bootstrap(repo) _, _, raw1 = run_cli("migrate", "enterprise-heavy") _, _, raw2 = run_cli("migrate", "enterprise-heavy") diff --git a/tests/e2e/test_authoring_flow.py b/tests/e2e/test_authoring_flow.py index 2f8a8a6..bf43978 100644 --- a/tests/e2e/test_authoring_flow.py +++ b/tests/e2e/test_authoring_flow.py @@ -1,4 +1,4 @@ -"""Phase-2 gate (archived at tag archive/pre-github): the exact CLI sequence the plugin drives — +"""The exact CLI sequence the plugin drives — adopt -> scaffold -> commit x2 -> validate — via the direct contract. """ @@ -126,7 +126,7 @@ def test_commit_drift_guard_refuses_bad_token(repo): assert code == 4 and bad["status"] == "error" -# --- the full gate flow ----------------------------------------------------- +# --- the full flow ----------------------------------------------------- def test_full_authoring_flow_validates_green(repo): apply_cli("scaffold", "principle", "--project", "payments", "--id", "data-locality") diff --git a/tests/e2e/test_body_sections_detail.py b/tests/e2e/test_body_sections_detail.py index 4ef10dd..c5c656d 100644 --- a/tests/e2e/test_body_sections_detail.py +++ b/tests/e2e/test_body_sections_detail.py @@ -1,7 +1,7 @@ -"""Phase-20 gate (archived at tag archive/pre-github): richer methods & artifacts — schema + fixtures (D34). +"""Richer methods & artifacts — schema + fixtures. A type may declare an **advisory** ``body.sections`` and a method step an optional -``detail`` (spec 03 §3/§6). The core validates them structurally, carries them +``detail``. The core validates them structurally, carries them through materialization, and exposes ``sections`` on the loaded model — while ``scaffold``/``commit`` behaviour is unchanged (sections are guidance, not a gate). ``enterprise-heavy`` pins the enriched ``core-ea@1.1.0``, so adopting it @@ -38,7 +38,7 @@ def _bootstrap(repo: Path): def test_enriched_pack_validates(): - """The enriched fixture pack is structurally valid (spec 03 §9).""" + """The enriched fixture pack is structurally valid.""" assert pack_mod.validate(pack_mod.load(PACK)) == [] @@ -52,7 +52,7 @@ def test_body_sections_survive_materialization(repo): def test_model_exposes_type_sections(repo): - """The loaded model surfaces sections in declared order (Phase-21/22 will read them).""" + """The loaded model surfaces sections in declared order.""" _bootstrap(repo) model = model_mod.load(Repo.discover()) cap = model.definitions.types["capability"] @@ -71,7 +71,7 @@ def test_step_detail_survives_materialization(repo): def test_scaffold_body_still_empty(repo): - """D34: sections are guidance only — ``scaffold`` still writes a front-matter-only + """Sections are guidance only — ``scaffold`` still writes a front-matter-only skeleton with an empty body (no pre-seeded headings).""" _bootstrap(repo) apply_cli("project", "create", "payments") @@ -84,7 +84,7 @@ def test_scaffold_body_still_empty(repo): def test_malformed_body_sections_rejected(): - """Structural guards: duplicate / invalid section id (spec 03 §3, D34).""" + """Structural guards: duplicate / invalid section id.""" dup = pack_mod.load(PACK) dup["artifact_types"][0]["body"]["sections"].append( {"id": "statement", "heading": "Dup", "guidance": "x"}) diff --git a/tests/e2e/test_cli_version.py b/tests/e2e/test_cli_version.py index f6084db..0e96567 100644 --- a/tests/e2e/test_cli_version.py +++ b/tests/e2e/test_cli_version.py @@ -1,4 +1,4 @@ -"""Phase-0 gate (archived at tag archive/pre-github): ea version envelope + exit code + reproducibility.""" +"""``ea version`` envelope + exit code + reproducibility.""" from __future__ import annotations @@ -17,7 +17,7 @@ def test_version_envelope_and_exit(): def test_version_output_is_reproducible(): _, _, raw1 = run_cli("version") _, _, raw2 = run_cli("version") - assert raw1 == raw2 # byte-identical (NFR-1) + assert raw1 == raw2 # byte-identical (P1) def test_unsupported_contract_version_is_usage_error(): diff --git a/tests/e2e/test_commit_diff.py b/tests/e2e/test_commit_diff.py index 2160371..19a123e 100644 --- a/tests/e2e/test_commit_diff.py +++ b/tests/e2e/test_commit_diff.py @@ -1,13 +1,12 @@ -"""Phase-29 gate (archived at tag archive/pre-github): reviewable commit delta — `data.diff` on the commit dry-run. +"""Reviewable commit delta — `data.diff` on the commit dry-run. Because the core performs the write, a re-commit (a new artifact version) was not reviewable: the dry-run returned the full ``preview`` (the after) but nothing showing *what changed* vs. disk. The core now emits a deterministic ``data.diff`` (unified diff of the assembled content against the current -file) on the ``commit`` dry-run — beside ``plan`` (which files) and ``preview`` (the after). Refines -spec 07 §4. First core change since Phase 27. +file) on the ``commit`` dry-run — beside ``plan`` (which files) and ``preview`` (the after). Both halves: the objective checks below, and a recorded re-commit session (the diff shown before the -confirm) captured in ``gates/phase-29.md`` (tag ``archive/pre-github``). +confirm) captured in a recorded session. """ from __future__ import annotations @@ -99,11 +98,11 @@ def test_both_hosts_teach_data_diff_at_review(): spine = (ROOT / "plugins" / host / ARCH / "SKILL.md").read_text() assert "data.diff" in authoring and "delta" in authoring.lower() assert "data.diff" in spine - # Presentation (post-D41 feedback): render it readably & proactively, not on demand. + # Presentation (later feedback): render it readably & proactively, not on demand. for text in (authoring, spine): assert "```diff" in text # a fenced diff block → red/green rendering assert "proactive" in text.lower() or "without being asked" in text.lower() - # authoring.md stays byte-identical across hosts (the D33 single-source invariant) + # authoring.md stays byte-identical across hosts (the single-source invariant) c = (ROOT / "plugins" / "ea-claude" / ARCH / "reference" / "authoring.md").read_bytes() a = (ROOT / "plugins" / "ea-antigravity" / ARCH / "reference" / "authoring.md").read_bytes() assert c == a diff --git a/tests/e2e/test_discovery_verbs.py b/tests/e2e/test_discovery_verbs.py index 024975f..58f155b 100644 --- a/tests/e2e/test_discovery_verbs.py +++ b/tests/e2e/test_discovery_verbs.py @@ -1,12 +1,12 @@ -"""Phase-17 gate (archived at tag archive/pre-github): preset & pack discovery — the read verbs that let a -surface enumerate the selectable building blocks before choosing one (spec 11 §6). +"""Preset & pack discovery — the read verbs that let a +surface enumerate the selectable building blocks before choosing one. An agent had no contract-native way to see the adoptable presets / packs: it shelled to ``ls``/``find`` and parsed internal YAML, and ``manifest adopt -`` named only the search path — the D31 "defaults to startup-light" root +`` named only the search path — the "defaults to startup-light" root cause. Four read verbs (``preset list``/``show``, ``pack list``/``show``) plus a self-describing not-found error that enumerates the valid ids inline close it. -All read-only (``ok``/exit 0), pin-native (``pack@version``), projectable (spec 09). +All read-only (``ok``/exit 0), pin-native (``pack@version``), projectable. """ from __future__ import annotations @@ -30,7 +30,7 @@ def env_paths(tmp_path, monkeypatch): def test_preset_list_summarizes_each_choice(env_paths): - """Per-preset summary → an agent compares + picks in one call (spec 11 §3.1).""" + """Per-preset summary → an agent compares + picks in one call.""" env, code, _ = run_cli("preset", "list") assert code == 0 and env["status"] == "ok" by_id = {p["id"]: p for p in env["data"]["presets"]} @@ -54,7 +54,7 @@ def test_preset_show_returns_the_full_resolved_preset(env_paths): def test_unknown_preset_enumerates_available_ids(env_paths): - """``preset show `` → exit 2 listing the valid ids (spec 11 §4).""" + """``preset show `` → exit 2 listing the valid ids.""" env, code, _ = run_cli("preset", "show", "bogus") assert code == 2 and env["status"] == "error" msg = env["diagnostics"][0]["message"] @@ -63,7 +63,7 @@ def test_unknown_preset_enumerates_available_ids(env_paths): def test_manifest_adopt_unknown_enumerates_presets(env_paths): - """The D31 root-cause command: ``adopt `` now teaches the choice. + """The root-cause command: ``adopt `` now teaches the choice. It routes through the same resolver, so fixing the resolver fixes adopt for free — proven on the very command that exhibited the gap. @@ -104,7 +104,7 @@ def test_unknown_pack_version_enumerates_available(env_paths): def test_bare_pack_id_requires_an_explicit_version(env_paths): - """Pin-native (D27): ``pack show core-ea`` enumerates that pack's versions.""" + """Pin-native: ``pack show core-ea`` enumerates that pack's versions.""" env, code, _ = run_cli("pack", "show", "core-ea") assert code == 2 and env["status"] == "error" msg = env["diagnostics"][0]["message"] @@ -112,14 +112,14 @@ def test_bare_pack_id_requires_an_explicit_version(env_paths): def test_discovery_reads_are_byte_stable(env_paths): - """Identical inputs → byte-identical stdout (NFR-1).""" + """Identical inputs → byte-identical stdout (P1).""" _, _, a = run_cli("pack", "list") _, _, b = run_cli("pack", "list") assert a == b and a.strip().startswith("{") def test_discovery_verbs_are_projectable(env_paths): - """Read verbs carry spec-09 projection: discover then trim (subtractive).""" + """Read verbs carry projection: discover then trim (subtractive).""" env, code, _ = run_cli("pack", "show", "core-ea@1.1.0", "--list-fields") assert code == 0 and "methods" in env["data"]["fields"] diff --git a/tests/e2e/test_drift_guard.py b/tests/e2e/test_drift_guard.py index 6023d4e..5876cc1 100644 --- a/tests/e2e/test_drift_guard.py +++ b/tests/e2e/test_drift_guard.py @@ -1,19 +1,19 @@ -"""Phase-13 gate (archived at tag archive/pre-github): multi-writer concurrency — resolved by DECISION (D26). +"""Multi-writer concurrency — resolved by DECISION. -Q11 is resolved **without** building a concurrency-control subsystem. The unit of +Concurrency is resolved **without** building a concurrency-control subsystem. The unit of work is a single writer on a git worktree/branch; **git** mediates reconciliation *between* writers (branch/merge/rebase, which never silently drop a write); and the -D5 confirmation-token drift guard already enforces single-writer safety *within* one -tree. Phase 13 is therefore rescoped from "implement a concurrency model" to a +confirmation-token drift guard already enforces single-writer safety *within* one +tree. This is therefore rescoped from "implement a concurrency model" to a one-line protocol hardening — a ``create`` now binds the prior absence of its path, so a create-create race trips the same drift guard as an update/delete — plus this -gate, which proves the end-to-end property the original phase demanded: **two writers +test, which proves the end-to-end property demanded: **two writers against the same source of truth never silently lose a write.** Three cases, one per layer of the model: 1. **intra-tree drift** — a second same-tree writer's stale ``--confirm`` is refused - (exit 4); the existing D5 mechanism *is* single-writer-per-worktree enforcement. + (exit 4); the existing mechanism *is* single-writer-per-worktree enforcement. 2. **create-create** — two writers creating the same artifact: the second is refused and the first's file is intact (no clobber). The protocol-level backstop for a caller without a pre-flight check is unit-tested in diff --git a/tests/e2e/test_full_surface_flow.py b/tests/e2e/test_full_surface_flow.py index 4a47336..d1a7689 100644 --- a/tests/e2e/test_full_surface_flow.py +++ b/tests/e2e/test_full_surface_flow.py @@ -1,15 +1,15 @@ -"""Phase-8 gate (archived at tag archive/pre-github): the second adapter surface. +"""The second adapter surface. -The Antigravity plugin is a *thin adapter* — it changes no core code (spec 08 §8); +The Antigravity plugin is a *thin adapter* — it changes no core code; its proof is that the **exact CLI sequence the plugin drives** runs green over the -unchanged contract. That sequence extends the Phase-2 flow (adopt → scaffold/commit -×2) with a final **promotion**, matching the gate's "tailors → authors → promotes": +unchanged contract. That sequence extends the flow (adopt → scaffold/commit +×2) with a final **promotion**, matching "tailors → authors → promotes": init → manifest adopt startup-light → scaffold/commit principle → scaffold/commit capability → promote principle → validate --all The conversational surface itself (the judgment layer) is proven separately by a -recorded real ``agy`` session under ``gates/phase-8.md`` (tag ``archive/pre-github``) (P5-3); this test pins the +recorded real ``agy`` session (P5-3); this test pins the contract path that session rides, including the two-phase ``--confirm`` token at every guarded write and the cross-scope fall-through after promotion. """ @@ -67,7 +67,7 @@ def test_full_surface_flow_authors_promotes_and_validates_green(repo): """The whole plugin sequence, end to end, lands green on the unchanged core.""" _author(repo) - # Flow C — promote the principle to Org via a reviewed, confirmed plan (spec 08 §6.5). + # Flow C — promote the principle to Org via a reviewed, confirmed plan. env, code, _ = apply_cli("promote", "principle", "data-locality", "--project", "payments") assert code == 0 and env["status"] == "ok" assert env["data"]["applied"] == {"created": 1, "updated": 0, "deleted": 1} @@ -89,7 +89,7 @@ def test_every_guarded_write_is_two_phase(repo): """Each guarded write the surface drives plans first (token), refusing a bare apply path. A dry-run returns a confirmation_token and writes nothing; only the --confirm re-run - applies. This is the one write protocol (spec 07 §8) the second surface reuses verbatim. + applies. This is the one write protocol the second surface reuses verbatim. """ # scaffold dry-run: token present, nothing on disk. plan, code, _ = run_cli("scaffold", "principle", "--project", "payments", diff --git a/tests/e2e/test_graph_dependency.py b/tests/e2e/test_graph_dependency.py index c49a4d9..02155d5 100644 --- a/tests/e2e/test_graph_dependency.py +++ b/tests/e2e/test_graph_dependency.py @@ -1,14 +1,14 @@ -"""Phase-5 gate (archived at tag archive/pre-github): read-side — the first ``graph`` kind, ``dependency``. +"""Read-side — the first ``graph`` kind, ``dependency``. A repository emits a deterministic, byte-stable dependency graph for one scope via direct CLI use, with **dangling references surfaced deterministically** -(the named gate criterion). Like ``coverage`` and unlike ``validate``, a graph +(the named criterion). Like ``coverage`` and unlike ``validate``, a graph *describes* and never judges — a dangling reference keeps the graph -``status: ok`` (exit 0); the invalid/exit-3 verdict is ``validate``'s alone -(spec 02 §4.1). Traversal respects visibility (spec 05 §3-4): a project's graph +``status: ok`` (exit 0); the invalid/exit-3 verdict is ``validate``'s alone. +Traversal respects visibility: a project's graph falls through to the Org artifacts it depends on, never into another project. -Cycle detection — the engine's third Phase-5 capability — is proven against the +Cycle detection — the engine's third capability — is proven against the engine directly in ``tests/unit/test_graph.py`` (the ``core-ea`` pack has no self-referential relationship to form one through the CLI). """ @@ -99,8 +99,8 @@ def test_dependency_graph_has_resolved_edge(repo): def test_project_graph_falls_through_to_org(repo): """A project capability governed-by an Org principle → a cross-scope edge. - The transitive closure pulls the Org node into the project's graph (spec 05 - §3 fall-through), proving traversal honours visibility. + The transitive closure pulls the Org node into the project's graph (fall-through), + proving traversal honours visibility. """ _bootstrap(repo) _write(repo, "org/business/principle/data-locality.md", PRINCIPLE) @@ -137,7 +137,7 @@ def test_dangling_reference_is_surfaced_not_a_failure(repo): def test_dependency_graph_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1) — the determinism gate.""" + """Identical inputs → byte-identical stdout (P1) — the determinism gate.""" _bootstrap(repo) _write(repo, "projects/payments/business/principle/data-locality.md", PRINCIPLE) _write(repo, "projects/payments/business/capability/billing.md", @@ -159,7 +159,7 @@ def test_empty_scope_is_an_empty_graph(repo): def test_missing_scope_is_a_usage_error(repo): - """No scope selector → usage error (exit 2), never a graph — spec 02 §9.""" + """No scope selector → usage error (exit 2), never a graph.""" _bootstrap(repo) env, code, _ = run_cli("graph", "dependency") assert code == 2 and env["status"] == "error" diff --git a/tests/e2e/test_headless_governance.py b/tests/e2e/test_headless_governance.py index f35d1fb..0e94080 100644 --- a/tests/e2e/test_headless_governance.py +++ b/tests/e2e/test_headless_governance.py @@ -1,7 +1,7 @@ -"""Phase-3 gate (archived at tag archive/pre-github): headless CI governance over the unchanged core. +"""Headless CI governance over the unchanged core. A CI job gates a build on ``ea validate --all``. The proof is provider-neutral: -it asserts the *contract* a pipeline relies on (spec 02 §4/§6/§11) rather than +it asserts the *contract* a pipeline relies on rather than any one CI system's YAML. The whole point of UC2 is the exit-code distinction — an **invalid architecture** (exit 3) must be separable from a **tooling/operator problem** (exit 1/2/4), and the JSON envelope on stdout is the machine-readable @@ -44,7 +44,7 @@ def _write(root: Path, rel: str, text: str): Rationale. """ -# A valid capability: has its owner and ≥1 governed-by principle (spec 06 §3.3). +# A valid capability: has its owner and ≥1 governed-by principle. CAPABILITY_OK = """\ --- domain: business @@ -58,7 +58,7 @@ def _write(root: Path, rel: str, text: str): Billing. """ -# spec 06 §4 Phase-3 fixture: a capability missing its governed-by relationship +# fixture: a capability missing its governed-by relationship # (cardinality 1..*), so the architecture is invalid though every file parses. CAPABILITY_BROKEN = """\ --- @@ -91,7 +91,7 @@ def test_valid_repo_passes_the_build(repo): def test_invalid_repo_fails_the_build(repo): - """Red build: the spec-06 fixture (capability missing governed-by) → exit 3 + report.""" + """Red build: the fixture (capability missing governed-by) → exit 3 + report.""" _bootstrap(repo) _write(repo, "projects/payments/business/capability/billing.md", CAPABILITY_BROKEN) env, code, raw = run_cli("validate", "--all") @@ -107,7 +107,7 @@ def test_tooling_problem_is_distinct_from_invalid(repo): """UC2: a usage problem is exit 2, never 3 — CI must not read it as 'invalid architecture'.""" _bootstrap(repo) _write(repo, "projects/payments/business/capability/billing.md", CAPABILITY_OK) - # No scope selector → usage error (spec 02 §9), distinct from a validation failure. + # No scope selector → usage error, distinct from a validation failure. env, code, _ = run_cli("validate") assert code == 2 and env["status"] == "error" assert code != 3 diff --git a/tests/e2e/test_inspection_verbs.py b/tests/e2e/test_inspection_verbs.py index 964c26c..bd2c1f5 100644 --- a/tests/e2e/test_inspection_verbs.py +++ b/tests/e2e/test_inspection_verbs.py @@ -1,10 +1,9 @@ -"""Phase-21 gate (archived at tag archive/pre-github): type & method inspection verbs (archived at tag archive/pre-github). +"""Type & method inspection verbs. -Two facet read verbs hand the D34 guidance to the agent on demand: ``ea type show +Two facet read verbs hand the guidance to the agent on demand: ``ea type show `` (fields + field guidance + advisory body sections + relationship metadata) and ``ea method show `` (summary + requires + steps with detail). Both are -read-only (``ok``/exit 0), enumerate the active ids on a miss (the Phase-17 -pattern), and honour ``--fields`` projection (spec 09). ``enterprise-heavy`` pins +read-only (``ok``/exit 0), enumerate the active ids on a miss, and honour ``--fields`` projection. ``enterprise-heavy`` pins the enriched ``core-ea@1.1.0``. """ @@ -43,7 +42,7 @@ def test_type_show_returns_fields_sections_relationships(repo): # advisory body sections, in declared order assert [s["id"] for s in data["sections"]] == ["definition", "outcomes", "notes"] assert all(s["heading"] and s["guidance"] for s in data["sections"]) - # relationship METADATA only — no live candidates (spec 13 §1) + # relationship METADATA only — no live candidates gov = next(r for r in data["relationships"] if r["name"] == "governed-by") assert gov["target_type"] == "principle" and gov["cardinality"] == "1..*" assert "candidates" not in gov @@ -65,7 +64,7 @@ def test_method_show_returns_steps_with_detail(repo): assert data["requires"]["rules"] == ["caps-unique", "refs-resolve"] steps = data["steps"] assert all(s["guide"] for s in steps) # terse headline - assert all(s["detail"].strip() for s in steps) # the D34 learnable detail + assert all(s["detail"].strip() for s in steps) # the learnable detail assert steps[0]["produces"] == "capability" diff --git a/tests/e2e/test_manifest_domain_verbs.py b/tests/e2e/test_manifest_domain_verbs.py index e339d11..8a8110f 100644 --- a/tests/e2e/test_manifest_domain_verbs.py +++ b/tests/e2e/test_manifest_domain_verbs.py @@ -1,12 +1,12 @@ -"""Phase-24 gate (archived at tag archive/pre-github): the ``ea manifest domain add|set-types|remove`` verb -family — incremental manifest tailoring (D36, spec 04 §4.1). +"""The ``ea manifest domain add|set-types|remove`` verb +family — incremental manifest tailoring. Extending a *live* manifest used to be half-supported: ``method add`` re-materializes ``definitions/`` but never touches the manifest ``domains``, so an incrementally added type lands unmapped and ``scaffold`` rejects it ("no domain permits type X"). The only fix was to clone a preset. This family closes that gap with guarded, in-place edits of ``domains`` that reuse ``manifest.validate_structural`` plus a -type↔active-type guard (spec 04 §9). +type↔active-type guard. The headline flow needs **no new fixture**: adopt ``startup-light`` → ``method add core-ea@1.1.0#data-modeling`` (``entity`` arrives unmapped) → ``manifest domain add diff --git a/tests/e2e/test_method_deprecation.py b/tests/e2e/test_method_deprecation.py index be54227..5ab2ae0 100644 --- a/tests/e2e/test_method_deprecation.py +++ b/tests/e2e/test_method_deprecation.py @@ -1,7 +1,7 @@ -"""Phase-11 gate (archived at tag archive/pre-github): method deprecation (archived at tag archive/pre-github). +"""Method deprecation. An org deprecates a method repository-wide through the Manifest's -``policies.methods..status`` section. The gate proves, over the existing +``policies.methods..status`` section. This proves, over the existing two-pack ``regulated-startup`` fixture, that deprecating ``control-mapping``: * is recorded keyed by **method id** (a guarded Manifest write); diff --git a/tests/e2e/test_pack_authoring_verbs.py b/tests/e2e/test_pack_authoring_verbs.py index 1165ba4..74a579e 100644 --- a/tests/e2e/test_pack_authoring_verbs.py +++ b/tests/e2e/test_pack_authoring_verbs.py @@ -1,12 +1,12 @@ -"""Phase-27 gate (archived at tag archive/pre-github): pack-authoring capability. +"""Pack-authoring capability. Two deterministic core verbs — ``ea pack new`` (guarded scaffold of a valid skeleton) and ``ea pack validate`` (the pure ``pack.validate`` checker surfaced as a read verb) — plus the -new ``ea-methodologist`` skill (host-parity, like Phase 19). The **compose** test proves an -authored pack materializes green **without a preset**, via the Phase-24/25 tailoring verbs. +new ``ea-methodologist`` skill (host-parity). The **compose** test proves an +authored pack materializes green **without a preset**, via the tailoring verbs. The recorded ea-methodologist session (model a described methodology → a validating, composing -pack) is the other half of the gate and lives in ``gates/phase-27.md`` (tag ``archive/pre-github``). +pack) is the other half — a recorded authoring session. """ from __future__ import annotations @@ -30,7 +30,7 @@ def sandbox(tmp_path, monkeypatch): # --- ea pack new ----------------------------------------------------------- def test_pack_new_scaffolds_a_skeleton_that_validates_unedited(sandbox): - """The §2.1 invariant: `pack new` → `pack validate` is green with ZERO edits.""" + """The invariant: `pack new` → `pack validate` is green with ZERO edits.""" env, code, _ = run_cli("pack", "new", "my-method", "--title", "My Method") assert code == 0 and env["status"] == "ok" assert env["data"]["plan"]["creates"] == ["packs/my-method/0.1.0/pack.yaml"] @@ -44,7 +44,7 @@ def test_pack_new_scaffolds_a_skeleton_that_validates_unedited(sandbox): def test_pack_new_is_byte_stable(sandbox): - """Same header → identical skeleton (NFR-1) — the token is content-bound.""" + """Same header → identical skeleton (P1) — the token is content-bound.""" a = run_cli("pack", "new", "p", "--title", "T")[0]["data"]["confirmation_token"] b = run_cli("pack", "new", "p", "--title", "T")[0]["data"]["confirmation_token"] assert a == b @@ -70,7 +70,7 @@ def test_pack_validate_reports_sorted_errors_exit3(sandbox): env, code, _ = run_cli("pack", "validate", str(p)) assert code == 3 and env["status"] == "invalid" and env["data"]["valid"] is False errs = env["data"]["errors"] - assert errs == sorted(errs) # deterministic order (NFR-1) + assert errs == sorted(errs) # deterministic order (P1) assert any("applies_to" in e for e in errs) and any("params.field" in e for e in errs) @@ -121,9 +121,9 @@ def test_authored_pack_composes_and_materializes_green(tmp_path, monkeypatch): # --- ea-methodologist skill: host single-source guard ----------------------- -# gate19 guards the same invariant for ea-architect only; this new skill needs its -# own guard against silent drift between its two plugin copies (D33 sync-by-copy). -# Two load-bearing checks (not the full gate19 battery): the copies stay in sync, +# test_skill_parity guards the same invariant for ea-architect only; this new skill needs its +# own guard against silent drift between its two plugin copies (sync-by-copy). +# Two load-bearing checks (not the full test_skill_parity battery): the copies stay in sync, # and the new skill is actually wired into the Antigravity manifest. CLAUDE = ROOT / "plugins" / "ea-claude" / "skills" / "ea-methodologist" diff --git a/tests/e2e/test_pack_enterprise_architecture.py b/tests/e2e/test_pack_enterprise_architecture.py index 31df33d..8c4cb76 100644 --- a/tests/e2e/test_pack_enterprise_architecture.py +++ b/tests/e2e/test_pack_enterprise_architecture.py @@ -1,14 +1,14 @@ -"""Phase-23b gate (archived at tag archive/pre-github): the Enterprise Architecture production pack + preset — -the rich, rigorous, four-domain end of the Phase-23 production library (D35). +"""The Enterprise Architecture production pack + preset — +the rich, rigorous, four-domain end of the production library. Grounded in the TOGAF Architecture Development Method (ADM) and its four-domain content metamodel (the ``togaf`` name is avoided as the id for trademark reasons; the framework is -referenced descriptively). Like the 23a/23c gates this resolves against the **production +referenced descriptively). Like the other production packs this resolves against the **production library home** (repo-root ``packs/`` + ``presets/``), proving the real, shippable -``enterprise-architecture`` pair end-to-end: the pack validates (spec 03 §9), the preset is -discoverable (spec 11) and adopts into its full closure (12 types / 7 methods / 26 rules), +``enterprise-architecture`` pair end-to-end: the pack validates, the preset is +discoverable and adopts into its full closure (12 types / 7 methods / 26 rules), the optional ``enum`` fields are surfaced by ``type show`` yet omitted from the scaffold, the -``decomposes-into`` + ``acyclic`` hierarchy fires, and — the 23b signature — the **rigorous +``decomposes-into`` + ``acyclic`` hierarchy fires, and — this pack's signature — the **rigorous traceability** holds: a full Technology → Application → Business realization spine commits and validates green, while the **first library use of the** ``must_be_referenced`` **rule kind** flags an orphan business service that no process realizes. @@ -39,7 +39,7 @@ @pytest.fixture def env_paths(tmp_path, monkeypatch): - """Resolve against the PRODUCTION home, not the fixtures (D35).""" + """Resolve against the PRODUCTION home, not the fixtures.""" monkeypatch.setenv("EA_PACK_PATH", str(ROOT / "packs")) monkeypatch.setenv("EA_PRESET_PATH", str(ROOT / "presets")) monkeypatch.chdir(tmp_path) @@ -63,13 +63,13 @@ def _commit(typ, aid, domain, front): assert code == 0 and env["status"] == "ok", env -# --- pack validity (spec 03 §9) -------------------------------------------- +# --- pack validity -------------------------------------------- def test_pack_validates(): assert pack_mod.validate(pack_mod.load(PACK)) == [] -# --- discovery (spec 11) ---------------------------------------------------- +# --- discovery ---------------------------------------------------- def test_preset_is_listed(env_paths): env, code, _ = run_cli("preset", "list") @@ -97,7 +97,7 @@ def test_pack_show_lists_twelve_types_and_seven_methods(env_paths): assert len(data["rules"]) == 26 -# --- adopt materializes the full closure (spec 03 §7) ---------------------- +# --- adopt materializes the full closure ---------------------- def test_adopt_materializes_full_closure(repo): types = {p.stem for p in (repo / "definitions/types").glob("*.yaml")} @@ -109,14 +109,14 @@ def test_adopt_materializes_full_closure(repo): # the seven acyclic hierarchies reached the store assert {"ent-requirements-acyclic", "ent-capabilities-acyclic", "ent-processes-acyclic", "ent-app-components-acyclic", "ent-tech-nodes-acyclic"} <= rules - # the six no-orphan traceability rules reached the store (the 23b signature) + # the six no-orphan traceability rules reached the store (this pack's signature) assert {"ent-requirements-satisfied", "ent-capabilities-supported", "ent-business-services-realized", "ent-app-services-provided", "ent-components-hosted", "ent-tech-services-provided"} <= rules assert "ent-refs-resolve" in rules -# --- optional-enum showcase + derive_stub fix (spec 13 §10) ---------------- +# --- optional-enum showcase + derive_stub fix ---------------- def test_optional_enums_are_shown_but_omitted_from_scaffold(repo): # type show surfaces the optional enums (discoverable, P4) @@ -141,7 +141,7 @@ def test_optional_enums_are_shown_but_omitted_from_scaffold(repo): def test_full_traceable_spine_commits_green(repo): """A complete Technology → Application → Business chain authored top-down, satisfying - every required edge AND all six no-orphan rules, validates green (the 23b signature).""" + every required edge AND all six no-orphan rules, validates green (this pack's signature).""" # governance _commit("architecture-principle", "secure-by-design", "governance", {"statement": "Security and privacy are designed in, never bolted on."}) diff --git a/tests/e2e/test_pack_fetch.py b/tests/e2e/test_pack_fetch.py index db56c84..d1c9585 100644 --- a/tests/e2e/test_pack_fetch.py +++ b/tests/e2e/test_pack_fetch.py @@ -1,13 +1,13 @@ -"""Phase-14 gate (archived at tag archive/pre-github): upstream pack registry & distribution — resolves Q5 (D27). +"""Upstream pack registry & distribution. An upstream *source* is a **git remote** or a **local directory**. ``ea pack fetch`` brings exact ``pack@version`` artifacts into a content-stable local **cache**; selection, materialization, and ``ea migrate`` then run **offline** against the -cache, deterministically and reproducibly (NFR-1/3). Version resolution is +cache, deterministically and reproducibly (P1). Version resolution is **pin-native** — a selection names an exact immutable ``pack@version``; evolving to a newer version is a deliberate ``ea migrate``, never an implicit float. A ``definitions/index.yaml`` lock records each active pack's content digest and -refuses a *same-version* drift (a published version is immutable — spec 03 §10). +refuses a *same-version* drift (a published version is immutable). Cases: 1. **git-remote fetch → offline select/materialize** — the source is deleted after diff --git a/tests/e2e/test_pack_lean_ux.py b/tests/e2e/test_pack_lean_ux.py index 959111f..721051c 100644 --- a/tests/e2e/test_pack_lean_ux.py +++ b/tests/e2e/test_pack_lean_ux.py @@ -1,16 +1,16 @@ -"""Phase-23c gate (archived at tag archive/pre-github): the Lean UX production pack + preset — the lighter, -startup/UI-UX on-ramp of the Phase-23 production library (D35). +"""The Lean UX production pack + preset — the lighter, +startup/UI-UX on-ramp of the production library. -Like the 23a flagship gate, this resolves against the **production library home** +Like the flagship Open Agile Architecture pack, this resolves against the **production library home** (repo-root ``packs/`` + ``presets/``), not ``tests/fixtures/`` — proving the real, -shippable ``lean-ux`` pair end-to-end: the pack validates (spec 03 §9), the preset is -discoverable (spec 11) and adopts into its full closure (8 types / 6 methods / 12 rules), +shippable ``lean-ux`` pair end-to-end: the pack validates, the preset is +discoverable and adopts into its full closure (8 types / 6 methods / 12 rules), the optional ``enum`` fields are surfaced by ``type show`` yet omitted from the scaffold, a leaf artifact commits green, and the ``decomposes-into`` + ``acyclic`` hierarchy fires. A final test proves the **composition story** the user accepted: a single manifest that adopts ``lean-ux`` and pulls in an ``open-agile-architecture`` method, then uses the -Phase-25 relationship overlay to add the two cross-pack edges (``metric`` measures +relationship overlay to add the two cross-pack edges (``metric`` measures ``outcome``; ``feature`` realizes ``capability``) — and both resolve green at validate. """ @@ -43,7 +43,7 @@ @pytest.fixture def env_paths(tmp_path, monkeypatch): - """Resolve against the PRODUCTION home, not the fixtures (D35).""" + """Resolve against the PRODUCTION home, not the fixtures.""" monkeypatch.setenv("EA_PACK_PATH", str(ROOT / "packs")) monkeypatch.setenv("EA_PRESET_PATH", str(ROOT / "presets")) monkeypatch.chdir(tmp_path) @@ -58,13 +58,13 @@ def repo(env_paths): return env_paths -# --- pack validity (spec 03 §9) -------------------------------------------- +# --- pack validity -------------------------------------------- def test_pack_validates(): assert pack_mod.validate(pack_mod.load(PACK)) == [] -# --- discovery (spec 11) ---------------------------------------------------- +# --- discovery ---------------------------------------------------- def test_preset_is_listed(env_paths): env, code, _ = run_cli("preset", "list") @@ -92,7 +92,7 @@ def test_pack_show_lists_eight_types_and_six_methods(env_paths): assert len(data["rules"]) == 12 -# --- adopt materializes the full closure (spec 03 §7) ---------------------- +# --- adopt materializes the full closure ---------------------- def test_adopt_materializes_full_closure(repo): types = {p.stem for p in (repo / "definitions/types").glob("*.yaml")} @@ -105,7 +105,7 @@ def test_adopt_materializes_full_closure(repo): assert "refs-resolve" in rules and len(rules) == 12 -# --- optional-enum showcase + derive_stub fix (spec 13 §10) ---------------- +# --- optional-enum showcase + derive_stub fix ---------------- def test_optional_enums_are_shown_but_omitted_from_scaffold(repo): # type show surfaces the optional enums (discoverable, P4) @@ -157,24 +157,24 @@ def test_decompose_cycle_is_rejected(repo): for d in val["diagnostics"]) -# --- composition with O-AA via the Phase-25 relationship overlay ------------ +# --- composition with O-AA via the relationship overlay ------------ def test_composes_with_oaa_via_overlay(env_paths): """One manifest, two packs: the overlay adds metric→outcome and feature→capability, - and both cross-pack edges resolve green at validate (the accepted 23c composition).""" + and both cross-pack edges resolve green at validate (the accepted composition).""" repo = env_paths apply_cli("init") apply_cli("manifest", "adopt", "lean-ux") apply_cli("project", "create", "demo") - # lean-ux + O-AA both ship a natural `refs-resolve` rule (Phase 26, D38): resolve the + # lean-ux + O-AA both ship a natural `refs-resolve` rule: resolve the # cross-pack clash with a manifest rename of the pack being pulled in, *before* the add. apply_cli("manifest", "rename", "add", "--pack", "open-agile-architecture", "--kind", "rule", "--from", "refs-resolve", "--to", "oaa-refs-resolve") # pull an O-AA method in, bringing its outcome + capability types into the closure apply_cli("method", "add", "open-agile-architecture@1.0.0#capability-mapping") - # method add writes definitions but not domains (D36) — map the new types into one + # method add writes definitions but not domains — map the new types into one apply_cli("manifest", "domain", "add", "oaa", "--types", "outcome,capability,principle") - # the two cross-pack overlay edges (D37): metric measures outcome, feature realizes capability + # the two cross-pack overlay edges: metric measures outcome, feature realizes capability apply_cli("manifest", "relationship", "add", "measures", "--source", "metric", "--target", "outcome", "--cardinality", "0..*") apply_cli("manifest", "relationship", "add", "realizes", diff --git a/tests/e2e/test_pack_open_agile_architecture.py b/tests/e2e/test_pack_open_agile_architecture.py index 95d1986..f76aace 100644 --- a/tests/e2e/test_pack_open_agile_architecture.py +++ b/tests/e2e/test_pack_open_agile_architecture.py @@ -1,10 +1,10 @@ -"""Phase-23a gate (archived at tag archive/pre-github): the Open Agile Architecture (O-AA) production pack + -preset — the flagship of the Phase-23 production library (D35). +"""The Open Agile Architecture (O-AA) production pack + +preset — the flagship of the production library. -Unlike every prior gate (which points at ``tests/fixtures/``), this one resolves +Unlike every prior suite (which points at ``tests/fixtures/``), this one resolves against the **production library home** — repo-root ``packs/`` + ``presets/`` — to prove the real, shippable ``open-agile-architecture`` pair end-to-end: the pack -validates (spec 03 §9), the preset is discoverable (spec 11) and adopts into the +validates, the preset is discoverable and adopts into the full closure (9 types / 7 methods / 18 rules), the optional ``enum`` fields the now-fixed ``derive_stub`` unblocked are surfaced by ``type show`` yet omitted from the scaffold, a leaf artifact commits green, and the broad ``decomposes-into`` + @@ -40,7 +40,7 @@ @pytest.fixture def env_paths(tmp_path, monkeypatch): - """Resolve against the PRODUCTION home, not the fixtures (D35).""" + """Resolve against the PRODUCTION home, not the fixtures.""" monkeypatch.setenv("EA_PACK_PATH", str(ROOT / "packs")) monkeypatch.setenv("EA_PRESET_PATH", str(ROOT / "presets")) monkeypatch.chdir(tmp_path) @@ -55,13 +55,13 @@ def repo(env_paths): return env_paths -# --- pack validity (spec 03 §9) -------------------------------------------- +# --- pack validity -------------------------------------------- def test_pack_validates(): assert pack_mod.validate(pack_mod.load(PACK)) == [] -# --- discovery (spec 11) ---------------------------------------------------- +# --- discovery ---------------------------------------------------- def test_preset_is_listed(env_paths): env, code, _ = run_cli("preset", "list") @@ -89,7 +89,7 @@ def test_pack_show_lists_nine_types_and_seven_methods(env_paths): assert len(data["rules"]) == 18 -# --- adopt materializes the full closure (spec 03 §7) ---------------------- +# --- adopt materializes the full closure ---------------------- def test_adopt_materializes_full_closure(repo): types = {p.stem for p in (repo / "definitions/types").glob("*.yaml")} @@ -102,7 +102,7 @@ def test_adopt_materializes_full_closure(repo): assert "refs-resolve" in rules and len(rules) == 18 -# --- optional-enum showcase + derive_stub fix (spec 13 §10) ---------------- +# --- optional-enum showcase + derive_stub fix ---------------- def test_optional_enums_are_shown_but_omitted_from_scaffold(repo): # type show surfaces the optional enums (discoverable, P4) diff --git a/tests/e2e/test_pack_version_migrate.py b/tests/e2e/test_pack_version_migrate.py index 55adf06..295b328 100644 --- a/tests/e2e/test_pack_version_migrate.py +++ b/tests/e2e/test_pack_version_migrate.py @@ -1,7 +1,6 @@ -"""Phase-10 gate (archived at tag archive/pre-github): cross-pack-**version** migration (resolves Q12). +"""Cross-pack-**version** migration. -``ea migrate pack@version`` makes a pack version bump first-class (spec 03 §10; -spec 04 §5). It re-pins every active method of that pack to a new **immutable** +``ea migrate pack@version`` makes a pack version bump first-class. It re-pins every active method of that pack to a new **immutable** version, re-materializes ``definitions/`` to the new closure, and **re-types** already-authored artifacts — re-validating them against the new types/rules and surfacing (never auto-fixing, never blocking) the incompatibilities the bump @@ -11,7 +10,7 @@ ``@1.0.0`` (minimal: capability/principle) and ``@1.1.0`` (adds entity/service modeling + an *optional* ``maturity`` field on ``capability``). ``startup-light`` pins ``@1.0.0``; migrating a startup-light repo to ``@1.1.0`` is the proving case. -This retires D18's "enrich ``core-ea@1.0.0`` in place" shortcut — the enrichment now +This retires the earlier "enrich ``core-ea@1.0.0`` in place" shortcut — the enrichment now lives in its **own** version, leaving ``@1.0.0`` immutable and still resolvable. """ @@ -217,7 +216,7 @@ def test_noop_when_already_pinned(repo): def test_version_migrate_plan_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1).""" + """Identical inputs → byte-identical stdout (P1).""" _bootstrap_startup_light(repo) _, _, raw1 = run_cli("migrate", "core-ea@1.1.0") _, _, raw2 = run_cli("migrate", "core-ea@1.1.0") diff --git a/tests/e2e/test_policies_carry_forward.py b/tests/e2e/test_policies_carry_forward.py index 0ecf0bc..796e63b 100644 --- a/tests/e2e/test_policies_carry_forward.py +++ b/tests/e2e/test_policies_carry_forward.py @@ -1,14 +1,13 @@ -"""Phase-12 gate (archived at tag archive/pre-github): durable governance across archetype operations (D25). +"""Durable governance across archetype operations. -A method deprecation lives in the Manifest's ``policies`` section (Phase 11, D23). +A method deprecation lives in the Manifest's ``policies`` section. Until now ``manifest adopt`` and archetype ``migrate`` rewrote the Manifest from the preset/merge and **dropped** that section, so a deprecation had to be re-issued after -evolving an archetype. This gate proves the merge now **carries org-authored governance -forward verbatim**: presets ship no policies (governance is layered *after* adoption, -spec 04 §6), so there is nothing to merge — only the org's live deprecation to preserve. +evolving an archetype. This proves the merge now **carries org-authored governance +forward verbatim**: presets ship no policies (governance is layered *after* adoption), so there is nothing to merge — only the org's live deprecation to preserve. Over the two-pack ``regulated-startup`` fixture (``control-mapping`` deprecates the -stranded ``control`` type), the gate shows that after ``migrate``/``adopt`` of an +stranded ``control`` type), the test shows that after ``migrate``/``adopt`` of an archetype the deprecation: * is **retained** — still blocks a new use and still grandfathers an existing one — @@ -118,7 +117,7 @@ def test_adopt_carries_deprecation_forward(repo): before = _deprecated(repo)["control-mapping"] # `adopt` rebuilds the Manifest from the preset wholesale; the org's governance is - # layered *after* adoption (spec 04 §6) and must be carried forward, not dropped. + # layered *after* adoption and must be carried forward, not dropped. apply_cli("manifest", "adopt", "regulated-startup") assert _deprecated(repo)["control-mapping"] == before # carried forward verbatim @@ -139,7 +138,7 @@ def test_carry_forward_is_byte_stable(repo): policies_text_before = "policies:" in (repo / MANIFEST).read_text("utf-8") assert policies_text_before - # The migrate plan is reproducible (NFR-1) even with a policy present… + # The migrate plan is reproducible (P1) even with a policy present… _, _, raw1 = run_cli("migrate", "enterprise-heavy") _, _, raw2 = run_cli("migrate", "enterprise-heavy") assert raw1 == raw2 and raw1.strip().startswith("{") diff --git a/tests/e2e/test_projection_cli.py b/tests/e2e/test_projection_cli.py index 8de86aa..bb4a533 100644 --- a/tests/e2e/test_projection_cli.py +++ b/tests/e2e/test_projection_cli.py @@ -1,14 +1,14 @@ -"""Phase-15 gate (archived at tag archive/pre-github): read-side projection — the subtractive ``--fields`` -primitive proven end-to-end through the CLI (spec 09 §6). +"""Read-side projection — the subtractive ``--fields`` +primitive proven end-to-end through the CLI. A surface fetches only the slice it needs: ``--fields`` trims a read command's ``data`` to the named top-level keys; ``--list-fields`` enumerates the set; an unknown field is a self-describing usage error (exit 2). Projection is read-only -— a projected ``validate`` keeps its exit-3 verdict — and byte-stable (NFR-1). -``graph dependency`` is deliberately *not* projectable in v0.1 (deferred — D29). +— a projected ``validate`` keeps its exit-3 verdict — and byte-stable (P1). +``graph dependency`` is deliberately *not* projectable in v0.1 (deferred). -The measured token-cost drop (the agent-track's reason for existing) is recorded -in ``gates/phase-15.md`` (tag ``archive/pre-github``); ``test_projection_shrinks_the_payload`` is its check. +The measured token-cost drop (the agent-track's reason for existing) is asserted +by ``test_projection_shrinks_the_payload``. """ from __future__ import annotations @@ -55,7 +55,7 @@ def test_fields_trims_to_named_top_level_keys(repo): def test_projection_is_byte_stable(repo): - """Identical inputs + identical --fields → byte-identical stdout (NFR-1).""" + """Identical inputs + identical --fields → byte-identical stdout (P1).""" _bootstrap(repo) _, _, raw1 = run_cli("report", "coverage", "--scope", "org", "--fields", "summary") _, _, raw2 = run_cli("report", "coverage", "--scope", "org", "--fields", "summary") @@ -106,7 +106,7 @@ def test_projected_validate_keeps_its_exit_3_verdict(repo): def test_graph_dependency_does_not_accept_fields(repo): - """Graph projection is deferred (D29): --fields is an unknown flag → exit 2.""" + """Graph projection is deferred: --fields is an unknown flag → exit 2.""" _bootstrap(repo) env, code, _ = run_cli("graph", "dependency", "--scope", "org", "--fields", "nodes") assert code == 2 and env["status"] == "error" @@ -123,7 +123,7 @@ def test_unprojected_read_is_unchanged(repo): def test_projection_shrinks_the_payload(repo): """The agent-track's reason for existing: the projected slice is smaller. - Recorded in gates/phase-15.md (tag archive/pre-github). With even one domain the per-domain matrix + With even one domain the per-domain matrix dominates; ``--fields summary`` keeps only the roll-up. """ _bootstrap(repo) diff --git a/tests/e2e/test_promote.py b/tests/e2e/test_promote.py index e18a793..7d7eeff 100644 --- a/tests/e2e/test_promote.py +++ b/tests/e2e/test_promote.py @@ -1,4 +1,4 @@ -"""Phase-6 gate (archived at tag archive/pre-github): write-side — ``ea promote`` (archived at tag archive/pre-github). +"""Write-side — ``ea promote``. A project artifact is promoted to the Org scope via a reviewed, confirmed plan — copied **verbatim**, the project file removed (no duplicate), inbound references @@ -6,12 +6,12 @@ make a blocked promotion a *verdict* on the proposed source of truth (``status: invalid``, exit 3, with the same diagnostic codes ``validate`` emits): -* a would-be-dangling outbound reference **blocks** (spec 05 §5); -* a same-``(type, id)`` Org artifact **refuses** — no shadowing (spec 05 §3.3). +* a would-be-dangling outbound reference **blocks**; +* a same-``(type, id)`` Org artifact **refuses** — no shadowing. -The outbound pre-check reuses the Phase-5 traversal engine (``outbound_refs``). +The outbound pre-check reuses the traversal engine (``outbound_refs``). The move is one guarded change, so plan/apply drift is refused (exit 4) by the -same verify-before-delete token that backs ``project delete`` (spec 05 §7). +same verify-before-delete token that backs ``project delete``. """ from __future__ import annotations @@ -102,14 +102,14 @@ def test_promote_plan_then_apply_moves_artifact(repo): assert code == 0 and env["status"] == "ok" assert env["data"]["applied"] == {"created": 1, "updated": 0, "deleted": 1} assert (repo / ORG_PRIN).exists() and not (repo / PROJ_PRIN).exists() - # Verbatim copy — no rewrite (spec 05 §5). + # Verbatim copy — no rewrite. assert (repo / ORG_PRIN).read_text("utf-8") == _principle("data-locality") def test_inbound_reference_falls_through_after_promotion(repo): """A project capability that referenced the artifact keeps resolving — to Org now. - The gate's "leaves a project reference, no duplicate": the project copy is gone, + The requirement "leaves a project reference, no duplicate": the project copy is gone, yet the capability's ``governed-by`` falls through to the Org copy with no rewrite. """ _bootstrap(repo) @@ -149,7 +149,7 @@ def test_would_dangle_outbound_blocks(repo): def test_shadow_refuses(repo): - """Org already holding the (type, id) refuses promotion — no shadowing (§3.3).""" + """Org already holding the (type, id) refuses promotion — no shadowing.""" _bootstrap(repo) _write(repo, ORG_PRIN, _principle("data-locality")) _write(repo, PROJ_PRIN, _principle("data-locality")) @@ -163,7 +163,7 @@ def test_shadow_refuses(repo): def test_promote_plan_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1).""" + """Identical inputs → byte-identical stdout (P1).""" _bootstrap(repo) _write(repo, PROJ_PRIN, _principle("data-locality")) _, _, raw1 = run_cli("promote", "principle", "data-locality", "--project", "payments") diff --git a/tests/e2e/test_relationship_overlay.py b/tests/e2e/test_relationship_overlay.py index e2a56bd..ac548f4 100644 --- a/tests/e2e/test_relationship_overlay.py +++ b/tests/e2e/test_relationship_overlay.py @@ -1,5 +1,5 @@ -"""Phase-25 gate (archived at tag archive/pre-github): the ``ea manifest relationship`` overlay — repo-level -cross-pack relationship tailoring (D37, spec 04 §4.2). +"""The ``ea manifest relationship`` overlay — repo-level +cross-pack relationship tailoring. A pack cannot declare a relationship whose ``target_type`` lives in another pack (pack validation + closure both reject a foreign target). So with the @@ -215,7 +215,7 @@ def test_remove_rejects_unknown_overlay_row(repo): assert code != 0 -# --- the overlay survives archetype operations (D37: carried like policies) -- +# --- the overlay survives archetype operations (carried like policies) -- def test_overlay_survives_migrate(repo): apply_cli("manifest", "relationship", "add", "addresses", diff --git a/tests/e2e/test_rename_overlay.py b/tests/e2e/test_rename_overlay.py index a3083d6..bd36def 100644 --- a/tests/e2e/test_rename_overlay.py +++ b/tests/e2e/test_rename_overlay.py @@ -1,4 +1,4 @@ -"""Phase-26 gate (archived at tag archive/pre-github): pack-independent materialization via a manifest +"""Pack-independent materialization via a manifest **rename overlay** (the accepted extended model b). Two packs may now ship the same natural id (every pack needs a ``refs-resolve``-style diff --git a/tests/e2e/test_report_coverage.py b/tests/e2e/test_report_coverage.py index 0adc2f2..5f6b9ff 100644 --- a/tests/e2e/test_report_coverage.py +++ b/tests/e2e/test_report_coverage.py @@ -1,10 +1,10 @@ -"""Phase-4 gate (archived at tag archive/pre-github): the first real ``report`` kind — ``coverage``. +"""The first real ``report`` kind — ``coverage``. A repository emits a deterministic, byte-stable ``coverage`` report as CI-consumable JSON via direct CLI use. Coverage answers "which permitted types -are present/missing per domain" (spec 04 §4) for one scope; unlike ``validate`` +are present/missing per domain" for one scope; unlike ``validate`` it describes rather than judges, so a sparse scope is still ``status: ok`` -(exit 0) — the invalid/exit-3 distinction (spec 02 §4.1) is not coverage's job. +(exit 0) — the invalid/exit-3 distinction is not coverage's job. """ from __future__ import annotations @@ -76,7 +76,7 @@ def _bootstrap(repo: Path): def test_coverage_reports_present_and_missing_per_domain(repo): - """The spec-06 fixture has a capability but no principle → one present, one missing.""" + """The fixture has a capability but no principle → one present, one missing.""" _bootstrap(repo) _write(repo, "projects/payments/business/principle/data-locality.md", PRINCIPLE) _write(repo, "projects/payments/business/capability/billing.md", CAPABILITY) @@ -111,7 +111,7 @@ def test_missing_type_is_reported_not_a_failure(repo): def test_coverage_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1) — the determinism gate.""" + """Identical inputs → byte-identical stdout (P1) — the determinism gate.""" _bootstrap(repo) _write(repo, "projects/payments/business/capability/billing.md", CAPABILITY) @@ -148,7 +148,7 @@ def test_org_scope_is_independent_of_projects(repo): def test_missing_scope_is_a_usage_error(repo): - """No scope selector → usage error (exit 2), never a report — spec 02 §9.""" + """No scope selector → usage error (exit 2), never a report.""" _bootstrap(repo) env, code, _ = run_cli("report", "coverage") assert code == 2 and env["status"] == "error" diff --git a/tests/e2e/test_running_methods_parity.py b/tests/e2e/test_running_methods_parity.py index 3aeae63..a8cc2a2 100644 --- a/tests/e2e/test_running_methods_parity.py +++ b/tests/e2e/test_running_methods_parity.py @@ -1,15 +1,15 @@ -"""Phase-28 gate (archived at tag archive/pre-github): guided method run — ``ea-architect`` walks a method. +"""Guided method run — ``ea-architect`` walks a method. -Surface-only — **no** ``src/ea_core`` change (like Phases 8/16/19). This phase adds ONE new +Surface-only — **no** ``src/ea_core`` change. This adds ONE new host-agnostic reference flow, ``reference/running-methods.md``, to the ``ea-architect`` skill: a method-agnostic, eliciting walk-through loop over the *existing* method data (``ea method show`` → ground on ``report coverage`` → walk each step, authoring each produced artifact via the reused Flow B -inner loop → advising-style summary). No core verb, no schema change (spec 15). +inner loop → advising-style summary). No core verb, no schema change. -The objective half extends the Phase-19 host-parity guard to the new file, and asserts the surface-only +The objective half extends the existing host-parity guard to the new file, and asserts the surface-only invariant directly: no ``ea method run``/``next`` core verb exists. The recorded ea-architect session -(walk a method end-to-end → several green artifacts → advisory summary) is the other half of the gate and -lives in ``gates/phase-28.md`` (tag ``archive/pre-github``). +(walk a method end-to-end → several green artifacts → advisory summary) is the other half — a recorded +guided-run session. """ from __future__ import annotations @@ -23,8 +23,8 @@ CLAUDE = ROOT / "plugins" / "ea-claude" / "skills" / "ea-architect" ANTI = ROOT / "plugins" / "ea-antigravity" / "skills" / "ea-architect" -# The new flow this phase adds. gate19 guards the full pre-existing set; this gate -# proves the new file joins it under the same single-source invariant (D33 sync-by-copy). +# The new flow this suite adds. test_skill_parity guards the full pre-existing set; this test +# proves the new file joins it under the same single-source invariant (sync-by-copy). NEW_FLOW = "running-methods" @@ -100,7 +100,7 @@ def test_no_core_method_run_verb_added(): def test_method_subcommands_unchanged_from_phase27(): - """The method verb catalog is exactly Phase 27's — this phase adds no CLI surface.""" + """The method verb catalog is unchanged — this suite adds no CLI surface.""" env, code, _ = run_cli("method", "bogus-subcommand") assert code == 2 msg = env["diagnostics"][0]["message"] # "...choose from add, remove, list, ..." diff --git a/tests/e2e/test_show_verb.py b/tests/e2e/test_show_verb.py index 6a6cfb7..9bea78c 100644 --- a/tests/e2e/test_show_verb.py +++ b/tests/e2e/test_show_verb.py @@ -1,4 +1,4 @@ -"""Proposal 0001 gate: ``ea show`` — single-artifact inspect verb. +"""``ea show`` — single-artifact inspect verb. ``ea show [--project ] [--fields …] [--list-fields]`` returns one resolved artifact's front-matter as flat top-level ``data`` keys plus the two @@ -278,7 +278,7 @@ def test_fields_trims_subtractively_including_absent_optional(repo): def test_projection_is_read_only(repo): - """--fields never touches status/diagnostics (spec 09 §3.1).""" + """--fields never touches status/diagnostics.""" _write(repo, "org/business/principle/data-locality.md", _principle("data-locality")) _write(repo, "org/business/capability/billing.md", _capability("billing")) bare, _, _ = run_cli("show", "capability", "billing") diff --git a/tests/e2e/test_skill_parity.py b/tests/e2e/test_skill_parity.py index 5952108..208deea 100644 --- a/tests/e2e/test_skill_parity.py +++ b/tests/e2e/test_skill_parity.py @@ -1,8 +1,8 @@ -"""Phase-19 gate (archived at tag archive/pre-github): architect advisory assistant + multi-file skill restructure (archived at tag archive/pre-github). +"""Architect advisory assistant + multi-file skill restructure. -Surface-only — **no** ``src/ea_core`` change (like Phases 8/16). The ``ea-architect`` skill is +Surface-only — **no** ``src/ea_core`` change. The ``ea-architect`` skill is restructured into *one skill, multi-file progressive disclosure*: a lean ``SKILL.md`` spine plus -one-level-deep ``reference/`` files loaded on demand. The objective half of the gate is the +one-level-deep ``reference/`` files loaded on demand. The objective half is the **host-parity invariant** that proves the two surfaces re-host the SAME judgment+advisory agent (P2): * every ``reference/`` file is 100% host-agnostic → **byte-identical** across both plugins; @@ -12,7 +12,7 @@ * the ``/ea`` launcher is byte-identical and host-agnostic across both plugins. The recorded advisory session (ask-state → synthesized picture → grounded next-steps) is the -other half of the gate and lives in ``gates/phase-19.md`` (tag ``archive/pre-github``). +other half — a recorded advisory session. """ from __future__ import annotations @@ -28,7 +28,7 @@ "discovery", "tailoring", "authoring", - "running-methods", # Phase 28 (D40) — guided method run; guarded in full by test_running_methods_parity + "running-methods", # guided method run; guarded in full by test_running_methods_parity "promotion", "migration", "reading", @@ -48,7 +48,7 @@ def test_reference_files_present_exactly_both_hosts(): def test_reference_files_byte_identical_across_hosts(): - """The single-source invariant: reference/ files sync verbatim (host-agnostic, D33 fork 6).""" + """The single-source invariant: reference/ files sync verbatim (host-agnostic).""" for name in REFERENCE_FILES: c = (CLAUDE / "reference" / f"{name}.md").read_bytes() a = (ANTI / "reference" / f"{name}.md").read_bytes() @@ -66,7 +66,7 @@ def test_reference_files_carry_no_host_token(): def test_skill_spine_differs_only_by_host_line(): - """The two spines are identical apart from the one marked host line (Phase-16 corral, kept).""" + """The two spines are identical apart from the one marked host line (the corral, kept).""" assert _body_without_host_line(CLAUDE / "SKILL.md") == _body_without_host_line(ANTI / "SKILL.md") claude_host = [ln for ln in (CLAUDE / "SKILL.md").read_text().splitlines() if "host:" in ln] anti_host = [ln for ln in (ANTI / "SKILL.md").read_text().splitlines() if "host:" in ln] diff --git a/tests/e2e/test_source_of_truth_flow.py b/tests/e2e/test_source_of_truth_flow.py index 3ec7413..c048b9c 100644 --- a/tests/e2e/test_source_of_truth_flow.py +++ b/tests/e2e/test_source_of_truth_flow.py @@ -1,4 +1,4 @@ -"""Phase-1 gate (archived at tag archive/pre-github): full source-of-truth flow via the direct CLI.""" +"""Full source-of-truth flow via the direct CLI.""" from __future__ import annotations diff --git a/tests/e2e/test_two_pack_compose.py b/tests/e2e/test_two_pack_compose.py index 4073585..08ec834 100644 --- a/tests/e2e/test_two_pack_compose.py +++ b/tests/e2e/test_two_pack_compose.py @@ -1,8 +1,8 @@ -"""Phase-9 gate (archived at tag archive/pre-github): breadth — a **second Method Pack** (archived at tag archive/pre-github). +"""Breadth — a **second Method Pack**. A second, self-contained pack (`risk-controls@1.0.0` — a risk register + the controls that mitigate risks, a different domain than `core-ea`) is selectable -**alongside** `core-ea`. The gate proves three things over the **unchanged** core: +**alongside** `core-ea`. This proves three things over the **unchanged** core: * a Manifest selecting methods from **two** packs materializes one `definitions/` drawn from both and **validates green** — each materialized file keeps its own @@ -13,7 +13,7 @@ a rule that only a *selected* method requires (`risk-mitigated`) is the one that governs. -The only core change is an additive collision guard in ``materialize`` (D21); the +The only core change is an additive collision guard in ``materialize``; the pack itself is pure data (M4). """ @@ -213,7 +213,7 @@ def test_same_pack_sharing_a_type_is_not_a_false_collision(repo): # --- determinism ------------------------------------------------------------ def test_two_pack_adopt_plan_is_byte_stable(repo): - """Identical inputs → byte-identical stdout (NFR-1).""" + """Identical inputs → byte-identical stdout (P1).""" apply_cli("init") _, _, raw1 = run_cli("manifest", "adopt", "regulated-startup") _, _, raw2 = run_cli("manifest", "adopt", "regulated-startup")