feat(packaging): non-invasive embedded layout + ARM/ARA projector + formalize/lock-check#687
Open
atom525 wants to merge 10 commits into
Open
feat(packaging): non-invasive embedded layout + ARM/ARA projector + formalize/lock-check#687atom525 wants to merge 10 commits into
atom525 wants to merge 10 commits into
Conversation
11cd698 to
1f0c8e8
Compare
atom525
added a commit
that referenced
this pull request
May 21, 2026
CI's docs job (`mkdocs build --strict`) failed on PR #687 with: WARNING - Doc file 'foundations/embedded-layout.md' contains a link '../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md', but the target 'specs/...' is not found among documentation files. Aborted with 1 warnings in strict mode! Two root causes: 1. The relative link from `docs/foundations/embedded-layout.md` to `../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md` — that file only exists on the `codex/arm-ara-gaia-projection-spec` PR branch, not on `main`. Replace the relative link with an absolute GitHub URL pinned to that branch so the link remains valid regardless of whether the spec PR is merged later. 2. The new `docs/foundations/embedded-layout.md` was not listed under any `nav:` entry. Strict mode also flags unlisted pages. Add it under "Foundational Docs → Gaia Lang Design → Embedded Layout" — that group already collects the package-model docs, so the new page sits next to its closest neighbour (`foundations/gaia-lang/package.md`). Verified locally with `uv run --extra docs mkdocs build --strict`: exit 0, no warnings. Co-authored-by: Cursor <cursoragent@cursor.com>
atom525
added a commit
that referenced
this pull request
May 21, 2026
CI's wheel-smoke job on PR #687 failed with: ModuleNotFoundError: No module named 'tomlkit' File ".../gaia/cli/commands/pkg/migrate.py", line 34, in <module> import tomlkit `gaia pkg migrate --remove-legacy` uses tomlkit to strip the [tool.gaia] block from a host pyproject.toml without losing comments, key order, or other [tool.*] sub-tables. tomlkit was already in the project's dev dep tree (via pre-commit / commitizen) so the in-repo `uv sync --extra dev` venv had it, but the shipped wheel's runtime deps did not — every wheel-smoke check that exercises the gaia CLI (`gaia --help` walks every command module at import time) hits the migrate import and fails. Promote tomlkit to a runtime dependency in [project].dependencies. Verified locally: uv build uv pip install --python /tmp/wheel-smoke/bin/python \ dist/gaia_lang-0.5.0-py3-none-any.whl /tmp/wheel-smoke/bin/gaia --help # OK /tmp/wheel-smoke/bin/python -c \ "import gaia.engine.{bp,ir,lang,inquiry,trace,packaging}, \ gaia.cli.commands.pkg.{mount,migrate,formalize,lock_check}; \ print('OK')" # OK Co-authored-by: Cursor <cursoragent@cursor.com>
9f57cc5 to
f0be7f9
Compare
atom525
added a commit
that referenced
this pull request
May 21, 2026
CI's docs job (`mkdocs build --strict`) failed on PR #687 with: WARNING - Doc file 'foundations/embedded-layout.md' contains a link '../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md', but the target 'specs/...' is not found among documentation files. Aborted with 1 warnings in strict mode! Two root causes: 1. The relative link from `docs/foundations/embedded-layout.md` to `../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md` — that file only exists on the `codex/arm-ara-gaia-projection-spec` PR branch, not on `main`. Replace the relative link with an absolute GitHub URL pinned to that branch so the link remains valid regardless of whether the spec PR is merged later. 2. The new `docs/foundations/embedded-layout.md` was not listed under any `nav:` entry. Strict mode also flags unlisted pages. Add it under "Foundational Docs → Gaia Lang Design → Embedded Layout" — that group already collects the package-model docs, so the new page sits next to its closest neighbour (`foundations/gaia-lang/package.md`). Verified locally with `uv run --extra docs mkdocs build --strict`: exit 0, no warnings. Co-authored-by: Cursor <cursoragent@cursor.com>
atom525
added a commit
that referenced
this pull request
May 21, 2026
CI's wheel-smoke job on PR #687 failed with: ModuleNotFoundError: No module named 'tomlkit' File ".../gaia/cli/commands/pkg/migrate.py", line 34, in <module> import tomlkit `gaia pkg migrate --remove-legacy` uses tomlkit to strip the [tool.gaia] block from a host pyproject.toml without losing comments, key order, or other [tool.*] sub-tables. tomlkit was already in the project's dev dep tree (via pre-commit / commitizen) so the in-repo `uv sync --extra dev` venv had it, but the shipped wheel's runtime deps did not — every wheel-smoke check that exercises the gaia CLI (`gaia --help` walks every command module at import time) hits the migrate import and fails. Promote tomlkit to a runtime dependency in [project].dependencies. Verified locally: uv build uv pip install --python /tmp/wheel-smoke/bin/python \ dist/gaia_lang-0.5.0-py3-none-any.whl /tmp/wheel-smoke/bin/gaia --help # OK /tmp/wheel-smoke/bin/python -c \ "import gaia.engine.{bp,ir,lang,inquiry,trace,packaging}, \ gaia.cli.commands.pkg.{mount,migrate,formalize,lock_check}; \ print('OK')" # OK Co-authored-by: Cursor <cursoragent@cursor.com>
Add a second on-disk layout for Gaia knowledge packages that lives entirely inside two reserved sub-folders of any host directory: <host>/gaia/ user-authored Gaia DSL (.py + gaia.toml) <host>/.gaia/ generated artifacts (was already this name) The host's own pyproject.toml, src/, ARM/ARA logic/, etc. are not touched. The new layout drops the `-gaia` distribution-name suffix and the [tool.gaia] block; identity moves into a strict pydantic v2 GaiaManifest in gaia/gaia.toml. The loader stays backward-compatible: detect_layout() picks embedded when present and legacy otherwise. Embedded source is loaded under a deterministic synthetic Python name (_gaia_pkg_<slug>_<sha8>) so the user-source folder literally called `gaia/` cannot shadow the installed gaia-lang library. When both layouts coexist on the same host detect_layout emits a warning and `gaia build compile` echoes the same precedence note to stderr. Cross-package fills() resolution learns the new layout: the dependency-root locator now recognises three manifest shapes so an embedded consumer can fill a legacy dependency's local_hole end-to-end (proven by tests/test_cross_layout_fills.py). A new gaia.engine.codegen module re-exports the author CLI's writer helpers (_ensure_engine_lang_imports / _maybe_update_all_block / _move_all_to_end) and adds AST-based render_call_statement / render_module so any future generated module shares one canonical shape with hand-authored author-CLI output. Verified: galileo + mendel example packages compile to byte-identical IR hashes through both the legacy layout and the embedded layout. Suppression budget: 27 -> 29. The two added suppressions are the standard `import tomli as tomllib # type: ignore[no-redef]` Python 3.10-compatible fallback that every other gaia.engine module already carries (see gaia/engine/packaging.py, gaia/engine/lang/runtime/ package.py); no semantic suppression added. Co-authored-by: Cursor <cursoragent@cursor.com>
Implements PR #675 spec sections 6 / 7 / 11 / 14.1: the deterministic projector that turns ARM bundles (`arm_manifest.json`, `knowledge/ claims.json`, `characterization.json`) and ARA artifacts (`PAPER.md`, `logic/claims.md`, `logic/related_work.md`, `logic/problem.md`, `logic/experiments.md`, `evidence/tables/*`, `trace/exploration_tree .yaml`) into a structured Gaia knowledge package. Modules: gaia/engine/projector/host_kind.py Structural detector: ARM via `arm_manifest.json`, ARA via `PAPER.md`+`logic/`, plain Python via `pyproject.toml`, generic fallback. gaia/engine/projector/api.py Public ProjectionResult / SourceMapRecord / QueueItem dataclasses; `project_host(host, seeds=..., host_kind=...)` dispatcher; `render_source_map(...)` rendering matching spec section 9. gaia/engine/projector/{generic,arm,ara}.py Per-host-kind projectors. All emit only safe records (`note`, `claim`, `observe`, `depends_on`) and never invent unreviewed warrants like `derive` / `infer` / `equal` / `contradict` / `exclusive` (spec section 2.2 conservatism). Ambiguous records get a follow-up entry in `.gaia/formalization_queue.jsonl` (spec section 10) listing the legal upgrade paths. ARA improvements vs. an earlier draft: - heading vs body separation so `claim(content=..., title=...)` holds the actual scientific assertion, not the heading twice; - PAPER.md frontmatter parsed into a `paper.py` note; - logic/problem.md + logic/experiments.md projected to `narrative.py` notes; - trace/exploration_tree.yaml `dead_end` branches projected to `trace.py` notes plus review queue items; - evidence/tables/*.md pipe-table column headers + row counts surfaced in the generated `observe(...)` rationale; - `Status: refuted` and `Refutes: [Cxx]` both seed contradict queue candidates (spec section 7.1). All generated Python source is built through `gaia.engine.codegen` (introduced in the previous commit) so escaping, alphabetical `__all__` management, and engine-lang imports match what the `gaia author <verb>` CLI writes byte-for-byte. Suppression budget: 29 -> 40 (+11). Breakdown: - 2 `# noqa: C901` on `project_ara` / `project_arm` (one per host kind; each function dispatches over every spec source class and is inherently long but trivially flat); - 9 `# noqa: F401,F403` inside string templates that the projector emits into the USER'S generated `gaia/from_{ara,arm}/__init__.py` so the downstream package's own ruff does not complain about the wildcard re-export shape; these are template literals, not suppressions in the projector's own source. Co-authored-by: Cursor <cursoragent@cursor.com>
CLI front-end for the embedded layout + spec sections 4 / 5.2 / 5.3
/ 16 (Phase 3 register-for-embedded).
New verbs under `gaia pkg`:
gaia pkg mount [--reproject] [--from <file>] [--host-kind ...]
Non-invasively mount Gaia onto any host. Auto-detects ARM / ARA
/ python-package / generic host kind, runs the deterministic
projector, writes gaia/gaia.toml + gaia/__init__.py +
gaia/from_<kind>/*.py + .gaia/source_map.json +
.gaia/formalization_queue.jsonl. The --reproject flag wipes only
the projector-managed gaia/from_*/ subdirectories so user-
authored gaia/__init__.py, gaia/formalization/, and any sibling
modules survive across re-projections (idempotency property
pinned by test_mount_reproject_preserves_user_files).
gaia pkg migrate [--remove-legacy]
Migrate a legacy `[tool.gaia]`+`src/<import>/` package to the
embedded layout. Copies the DSL source, rewrites absolute
imports of the legacy import name to relative form via the
standard library's AST/regex, writes gaia/gaia.toml from the
legacy block, optionally strips `[tool.gaia]` from pyproject
using tomlkit so comments + key order + other [tool.*] tables
survive. Verified byte-identical IR hash before and after on
the shipping galileo-v0-5-gaia example.
gaia pkg formalize [--auto-accept depends_on:infer]
[--interactive | --no-interactive]
[--batch-name <name>]
Spec section 5.2 upgrade pass. Walks
.gaia/formalization_queue.jsonl and turns scaffold records into
formal warrants written to gaia/formalization/<batch>.py.
Reversible: deleting the batch + resetting the queue entry's
`status` to `"open"` restores the pre-upgrade IR. infer()
upgrades emit conservative `p_e_given_h=0.5, p_e_given_not_h=0.5`
placeholders tagged with `TODO(reviewer): ...` in the rationale;
the lock-check gate (next verb) refuses to ship until those
markers are replaced.
gaia pkg lock-check
Spec section 5.3 publish gate. Reuses
`gaia.engine.packaging.{load_gaia_package, apply_package_priors,
compile_loaded_package_artifact, validate_fills_relations}`
plus `gaia.engine._stale_check.check_compiled_artifacts` so
failures match `gaia build check` byte-for-byte. Adds two
embedded-specific checks: every source_map record's
generated_file + source_path must still exist on disk, and no IR
record may still carry the `TODO(reviewer)` placeholder marker.
Existing verbs touched (back-compat preserved):
gaia build init --embedded <path>
Spec section 4 on-ramp; delegates to `gaia pkg mount`.
gaia build compile [--sync-host / --no-sync-host]
Default `--no-sync-host` for embedded layouts so the host's
pyproject.toml environment is not auto-synced. Also echoes the
dual-layout warning to stderr (logger output alone was easy to
miss).
gaia pkg register [--locked]
Spec section 16 Phase 3. When --locked is set, runs
`gaia pkg lock-check` first and refuses to publish on any
failure. Accepts embedded layouts (uuid lives under
`[package].uuid`; -gaia suffix no longer required).
gaia pkg scaffold
Relaxes the -gaia name requirement to a warning so the verb is
consistent with the embedded layout's stance.
Suppression budget: 40 -> 47 (+7). Breakdown:
- 2 `# noqa: B008` on typer.Option list defaults (the standard
Typer pattern, already in use elsewhere in this codebase);
- 1 `# noqa: C901` on `_check_todo_placeholders` which dispatches
over every IR field that could carry a TODO marker;
- 4 `# noqa: F401,F403` inside string templates that the mount
verb writes into user-generated `gaia/__init__.py` /
`gaia/from_*/__init__.py` files so downstream user ruff does
not complain about the placeholder import + wildcard re-export
shapes (template literals; not suppressions in our own code).
Co-authored-by: Cursor <cursoragent@cursor.com>
Add `docs/foundations/embedded-layout.md` covering: - the two-folder convention (gaia/ + .gaia/) and how it differs from the legacy `[tool.gaia]` + `src/<import>/` layout; - the pydantic GaiaManifest schema; - the synthetic-module loader strategy that lets the user-source folder be literally called `gaia/` without shadowing the installed `gaia-lang` library, with PEP 561 mypy stub packages cited as precedent for the side-loaded-semantic-layer pattern; - `gaia pkg mount --reproject` semantics: what survives, what gets rewritten; - the full new CLI surface (mount / migrate / formalize / lock-check / register --locked); - spec section -> implementation mapping table for PR #675; - explicit list of future work (LLM agent backend for `--auto-accept`, registry binding state machine beyond `source_only`). Adds a small README subsection under Quick Start so users discover `gaia build init --embedded` without having to read the foundations doc first. Co-authored-by: Cursor <cursoragent@cursor.com>
CI's docs job (`mkdocs build --strict`) failed on PR #687 with: WARNING - Doc file 'foundations/embedded-layout.md' contains a link '../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md', but the target 'specs/...' is not found among documentation files. Aborted with 1 warnings in strict mode! Two root causes: 1. The relative link from `docs/foundations/embedded-layout.md` to `../specs/2026-05-19-arm-ara-gaia-package-projection-spec.md` — that file only exists on the `codex/arm-ara-gaia-projection-spec` PR branch, not on `main`. Replace the relative link with an absolute GitHub URL pinned to that branch so the link remains valid regardless of whether the spec PR is merged later. 2. The new `docs/foundations/embedded-layout.md` was not listed under any `nav:` entry. Strict mode also flags unlisted pages. Add it under "Foundational Docs → Gaia Lang Design → Embedded Layout" — that group already collects the package-model docs, so the new page sits next to its closest neighbour (`foundations/gaia-lang/package.md`). Verified locally with `uv run --extra docs mkdocs build --strict`: exit 0, no warnings. Co-authored-by: Cursor <cursoragent@cursor.com>
CI's wheel-smoke job on PR #687 failed with: ModuleNotFoundError: No module named 'tomlkit' File ".../gaia/cli/commands/pkg/migrate.py", line 34, in <module> import tomlkit `gaia pkg migrate --remove-legacy` uses tomlkit to strip the [tool.gaia] block from a host pyproject.toml without losing comments, key order, or other [tool.*] sub-tables. tomlkit was already in the project's dev dep tree (via pre-commit / commitizen) so the in-repo `uv sync --extra dev` venv had it, but the shipped wheel's runtime deps did not — every wheel-smoke check that exercises the gaia CLI (`gaia --help` walks every command module at import time) hits the migrate import and fails. Promote tomlkit to a runtime dependency in [project].dependencies. Verified locally: uv build uv pip install --python /tmp/wheel-smoke/bin/python \ dist/gaia_lang-0.5.0-py3-none-any.whl /tmp/wheel-smoke/bin/gaia --help # OK /tmp/wheel-smoke/bin/python -c \ "import gaia.engine.{bp,ir,lang,inquiry,trace,packaging}, \ gaia.cli.commands.pkg.{mount,migrate,formalize,lock_check}; \ print('OK')" # OK Co-authored-by: Cursor <cursoragent@cursor.com>
f0be7f9 to
9ecd56e
Compare
…ain + typed related_work edges Per Ara paper §2.2 the Cognitive Layer is a "machine-executable dependency graph" with two structural backbones the previous projector flattened: 1. The forensic binding chain `claims.md -> experiments.md -> /evidence/`. The earlier projector skipped the experiments hop: `Proof: [E01]` projected directly to `depends_on(claim, given=[evidence_placeholder])`. Now `logic/experiments.md` is parsed into Exx blocks (Verifies / Procedure / Expected outcome / Evidence fields), emitted as `claim()` records in `gaia/from_ara/experiments.py` with `metadata.ara_kind = "verification_plan"`, and the chain materialises as `depends_on(claim, given=[experiment])` followed by `depends_on(experiment, given=[evidence_file])` when the experiment's Evidence: ref resolves to a real file. Empty experiments.md keeps the old two-segment fallback for backward compat. Experiments are `claim()` (not `note()`) because `depends_on` / `infer` / `derive` all require Claim arguments — the only Gaia knowledge type that participates in dependency edges. The `ara_kind` metadata flag distinguishes verification plans from falsifiable scientific claims. 2. The typed-edge semantics of `logic/related_work.md` `Type:` (imports / extends / bounds / baseline / refutes). The earlier projector dumped them all into the same generic queue item with `candidate_actions: ["gaia_pkg_add", "candidate_relation"]`. The new mapping (per Ara paper §2.2) preserves the actionable semantics: - `imports` / `extends` → `gaia_pkg_add` (registry dependency) - `bounds` → `gaia_pkg_add` + dependency_with_constraints kind - `baseline` → new `baseline_regression_check` candidate - `refutes` → `contradict` candidate (instead of generic) - unknown / missing → `gaia_pkg_add` source_only fallback The derived `related_work_kind` field is also surfaced in both the generated note's metadata and the source_map record's extras so downstream tools branch on the kind without re-parsing the raw `Type:` string. Spec §14.1 is still honoured — no auto-conversion to `gaia pkg add`; the typed candidate just makes the upgrade unambiguous when a reviewer picks it. Verified end-to-end on a 4-RW synthetic ResNet ARA host: 3 source files (`claims.md` + `experiments.md` + `evidence/tables/conv.md`) project into 11 knowledge nodes with `ara_c01 -> ara_experiment_e01 -> ara_evidence_evidence_tables_conv` chain reachable through the IR; 5 RW queue items each carry the right `candidate_actions[0]` (contradict / gaia_pkg_add / gaia_pkg_add / gaia_pkg_add / baseline_regression_check). Suppression budget: 47 -> 49 (+2). Breakdown: - 1 `# noqa: C901` on `_render_claim_module` — branchy because of the three-segment-vs-two-segment fallback dispatch (each Proof: ref picks experiment or evidence target); - 1 `# noqa: F401,F403` in the `_INIT_BODY` template's new `from .experiments import *` line (template literal in the user's generated `gaia/from_ara/__init__.py`, not a suppression in the projector's own source). Co-authored-by: Cursor <cursoragent@cursor.com>
Add package, node, calibration, manifest, status, red-team, diff, gate, query, and report review commands behind a shared ReviewReport schema. The implementation reuses inquiry, trace, BP, ReviewManifest, and semantic diff backends while adding tests and CLI help baselines for the new review workflow. Co-authored-by: Cursor <cursoragent@cursor.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements PR #675 — the non-invasive ARM/ARA → Gaia projection design — end to end:
gaia/(user-authored DSL +gaia.tomlidentity) and.gaia/(generated artifacts). The host's ownpyproject.toml,src/, ARM/ARAlogic/,evidence/, etc. stay untouched. No-gaiadistribution-name suffix required.arm_manifest.json,knowledge/claims.json,characterization.json) and ARA artifacts (PAPER.md,logic/claims.md,logic/related_work.md,logic/problem.md,logic/experiments.md,evidence/tables/*,trace/exploration_tree.yaml) into compilable Gaia source plus the spec §9 / §10 audit spine (.gaia/source_map.json,.gaia/formalization_queue.jsonl).gaia pkg formalizewalks the queue and turnsdepends_on(...)scaffolds intoinfer(...)/derive(...)warrants, linked back throughmaterialize(...)so the audit chain stays intact and the upgrade is reversible.gaia pkg lock-checkvalidates source-hash freshness, manifest freshness, queue cleanliness, and refuses to ship while anyinfer(...)warrant still carries the placeholderTODO(reviewer)marker;gaia pkg register --lockedruns the gate as a precondition.gaia pkg migrate [--remove-legacy]ports a legacy[tool.gaia]+src/<import>/package to the embedded layout and produces byte-identical IR.Verified end-to-end on the shipping examples
Spec coverage (PR #675)
gaia/+.gaia/gaia build init --embedded+gaia pkg mountgaia.engine.projector.{generic,ara,arm}gaia pkg formalize(interactive +--auto-acceptrules)gaia pkg lock-check,register --lockedgaia.engine.projector.armgaia.engine.projector.ara(PAPER, claims, evidence, related_work, problem, experiments, trace)gaia.engine.projector.api.render_source_mapQueueItem.to_jsonproject_host(...)source_only; future forcandidate_match/registry_match(needs registry resolver)gaia.engine.packaging._load_embedded_package_modulesgaia pkg register --lockedreadsgaia.toml.[package].uuidComponent reuse (audited)
Every new CLI verb / projector module reuses existing Gaia engine surface where one exists —
gaia.engine.packaging.{load_gaia_package, apply_package_priors, compile_loaded_package_artifact, build_package_manifests, validate_fills_relations, write_compiled_artifacts},gaia.engine.ir.validator.validate_local_graph,gaia.engine._stale_check.check_compiled_artifacts,gaia.cli.commands.author._envelope,gaia.engine.langDSL. A newgaia.engine.codegenmodule re-exports the author CLI's writer helpers (_ensure_engine_lang_imports/_maybe_update_all_block/_move_all_to_end) so projector-generated source and author-CLI-written source share a single canonical shape.Test plan
make test(pr_gate slice) — 952 passed / 15 skipped / 0 failed locallyuv run mypy --strict— clean on 142 source filesuv run ruff check .+ruff format --check .— cleanuv run python scripts/check_ir_schema_bump.py— cleanuv run python scripts/check_suppression_budget.py— clean (budget bumped 27 → 47 with per-commit justification)examples/galileo-v0-5-gaia(legacy = embedded = migrated)examples/mendel-v0-5-gaia(legacy)register --lockedblocks before any registry side effectsgaia/__init__.py+ sibling user modules; onlygaia/from_*/is rewritten15 new tests under
tests/test_embedded_layout.py,tests/test_projector_ara.py,tests/test_pkg_migrate.py,tests/test_pkg_formalize_lock.py,tests/test_cross_layout_fills.py— all markedpr_gate.Known future-work boundaries (out of scope for this PR)
--formalize agentmode — the deterministic surface and the--auto-accept rule:actioninterface are in place; the LLM agent is a separate package.candidate_match/registry_matchstates for ARArelated_work— needs a real Gaia registry resolver (DOI / arXiv lookup); current implementation shipssource_onlyonly.