Skip to content

Support recursive design: additive multi-file MTHDS libraries#970

Open
lchoquel wants to merge 19 commits into
devfrom
feature/Support-recursive-design
Open

Support recursive design: additive multi-file MTHDS libraries#970
lchoquel wants to merge 19 commits into
devfrom
feature/Support-recursive-design

Conversation

@lchoquel
Copy link
Copy Markdown
Member

@lchoquel lchoquel commented Jun 7, 2026

Summary

Adds support for recursive / additive multi-file MTHDS library construction: a same-domain library can now be authored as separate, additive .mthds files (forward-declared headers + separate definitions) instead of one monolithic file. This unblocks parallel, top-down method construction.

Merge-time rules

  • Pipe signature ↔ concrete reconciliation. A PipeSignature (forward declaration / "header") and a concrete pipe with the same code reconcile — the concrete satisfies the signature instead of raising a duplicate-code error. Contracts are compared by normalized concept identity (bare ≡ domain-qualified, Textnative.Text, structural multiplicity), replacing the old raw-string contract_equals. Two concrete pipes, or genuinely different contracts, still error.
  • Cross-file concept resolution. Concept references resolve against the merged library instead of per file, so a concept declared once can be referenced by bare code from sibling files of the same domain (same directory batch or across separate load batches). A concept declared twice still raises ConceptLibraryError; an unresolvable reference now surfaces as a structured validation error instead of a raw traceback.
  • Order-independent domain-metadata merge. Domain description / system_prompt now merge order-independently across same-domain files: a membership-only file that omits them defers to whichever file declares them, instead of warning and racing on filesystem load order. The root header always wins over siblings that carry only domain = "...". Two files declaring different non-empty values still keep the first and warn. Implemented as a shared merge_domain_metadata_field helper wired into both the crate factory and the runtime DomainLibrary.

Validate surface

  • pending_signatures on a successful lenient validate. A successful validate bundle (notably --allow-signatures) now reports the library-wide set of pipes still declared as PipeSignature — surfaced as a pending_signatures array in the agent-CLI / builder JSON envelope and a "Pending signatures" markdown section, so a top-down build sees exactly what remains.

Test plan

  • make agent-check — clean (ruff, plxt, pyright, mypy).
  • make agent-test — full suite green.
  • New unit coverage under tests/unit/pipelex/libraries/ for signature/concrete reconciliation, normalized contract conformance, cross-file concept references, and the domain-metadata merge matrix (both load orders, same-value, conflict; across description + system_prompt, warnings asserted via caplog).

Documentation

Docs-site coverage added this cycle (reference level — the full top-down walkthrough is deferred, see Documentation Debt):

  • docs/building-methods/pipes/signature-pipes.md — new note: a signature and its concrete definition can live in separate sibling files of the same domain; loading merges them and they reconcile when contracts match. Points to the validate output.
  • docs/tools/cli/validate.md — new "Pending signatures" tip under Validate Bundle: a successful run reports pending_signatures (library-wide list of still-unimplemented PipeSignature headers), most useful on --allow-signatures.
  • docs/tools/cli/agent-cli.md — extended the signature note with the pending_signatures envelope field (JSON array + markdown section).

CHANGELOG.md [Unreleased] already carries the full feature entry (additive construction, reconciliation, cross-file concept resolution, domain-metadata merge, pending_signatures). pipelex/cli/agent_cli/CLAUDE.md documents the pending_signatures envelope field. Design records live in wip/recursivity/.

Documentation Debt

  • Critical → deferred by decision. No end-to-end "build a method top-down across multiple files" how-to / tutorial on the docs site yet. The runtime capability is complete, but the orchestrator that drives the workflow (mthds-vibe / mthds-signature-expander in mthds-plugins) is not built yet, so a detailed walkthrough now would risk drifting from the real flow. Write it once that orchestrator lands. Suggest a docs-debt label.
  • Reference-only coverage (acceptable for now): signature↔concrete reconciliation, cross-file concept resolution, and the domain-metadata merge rule are covered in CHANGELOG + wip/recursivity/ but have no dedicated how-to. Same trigger to expand: when the orchestrator ships.

🤖 Generated with Claude Code


Summary by cubic

Adds recursive, additive multi-file .mthds libraries for the same domain. Signatures reconcile with concretes, cross-file refs resolve across files/batches, and validate bundle returns pending_signatures (intentionally omitted by validate-all); works for dependencies and the concepts-only loader.

  • New Features

    • Signature ↔ concrete reconciliation with normalized contract matching (bare ≡ domain-qualified, Textnative.Text, multiplicity). Conflicting concretes or mismatched contracts still error.
    • Cross-file same-domain concept/pipe reference resolution against the merged library (within a batch and across batches). Unresolvable refs return a structured validation error.
    • Order-independent merge of domain description and system_prompt. Membership-only files defer; conflicting non-empty values keep the first and warn.
    • validate bundle returns pending_signatures in JSON and renders a "Pending signatures" section; validate-all omits it by design.
  • Bug Fixes

    • Removed the per-file pipe-reference validator so qualified same-domain refs resolve post-merge like bare refs; missing refs are caught by merged validation.
    • Concepts-only loader now validates at the library level and batches sibling .mthds files so same-domain refs resolve regardless of filename order.
    • Dependency loading routes through LibraryCrateFactory, reconciling multi-file PipeSignature + concrete packages; genuine duplicates raise.
    • Canonical native-concept check in concept-ref validation (Text or native.Text only), fixing false skips for qualified refs like my_domain.Text.
    • Recorded deferred P3 polish in wip/recursivity/review-followups.md (docs only).

Written for commit b77726b. Summary will update on new commits.

Review in cubic

lchoquel and others added 10 commits June 7, 2026 14:03
…handling

- Added `contract_equals` method to `PipeBlueprint` for contract comparison.
- Introduced `duplicate_ref_msg` function for generating error messages on duplicate declarations.
- Enhanced `LibraryCrateFactory` to reconcile pipe declarations and handle collisions.
- Updated tests to cover new reconciliation logic and ensure correct behavior for signatures and concrete pipes.
…tion

- Removed the local concept reference validation from PipelexBundleBlueprint, allowing bundles to construct even when referencing concepts declared in sibling files.
- Added a new method in LibraryCrateFactory to validate concept references against the merged library after bundle construction.
- Created a new test suite for validating concept references at the library level, ensuring that undeclared references are caught during the merge process.
- Updated existing tests to reflect the new validation logic and removed obsolete tests related to local concept reference validation.
- Introduced new test cases to verify cross-file concept reference resolution and error handling for undeclared concepts.
…idation

- Changed `ConceptLibraryError` to inherit from `LibraryError` for better error categorization.
- Introduced `validate_concept_references_in_blueprints` function to validate same-domain concept references across multiple blueprints.
- Updated `LibraryCrateFactory` to remove in-factory concept reference validation, delegating it to the loader.
- Enhanced `LibraryManager` to validate concept references against the live library during blueprint loading.
- Added integration tests for cross-file and cross-batch concept reference resolution.
- Created unit tests for `validate_concept_references_in_blueprints` to cover various scenarios including undeclared concepts and native concept allowances.
…natures and enhance validation output

- Added `contracts_match` function to normalize and compare contracts between pipe signatures and their definitions.
- Updated `ValidateBundleResult` to include `pending_signatures`, reflecting unsatisfied forward declarations.
- Enhanced validation output to render pending signatures in markdown format.
- Introduced tests for pending signatures in validation results and contract reconciliation across equivalent concept spellings.
Update the recursive-design handoff trackers to reflect shipped work on
feature/Support-recursive-design:

- HANDOFF-recursive-followups.md: Task 1 (pending_signatures on a lenient
  validate) and Task 2 (normalized contract conformance) marked done, with
  as-built notes.
- HANDOFF-domain-metadata-merge.md: order-independent, omission-quiet domain
  metadata merge marked done (shared merge_domain_metadata_field helper wired
  into both the crate factory and the runtime DomainLibrary).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 7, 2026

Greptile Summary

This PR adds additive multi-file .mthds library construction. The main changes are:

  • Reconciles PipeSignature headers with concrete pipe definitions.
  • Resolves same-domain concept references against the merged library.
  • Merges domain metadata without depending on file load order.
  • Reports remaining pending_signatures from successful bundle validation.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Reviews (5): Last reviewed commit: "fix(library): use canonical native-conce..." | Re-trigger Greptile

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 28 files

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

lchoquel and others added 5 commits June 7, 2026 21:46
…ive-design

# Conflicts:
#	CHANGELOG.md
#	pipelex/cli/agent_cli/CLAUDE.md
…, and concepts-only

Three paths still did per-file / pre-merge work, breaking same-domain
authoring the merged crate is meant to resolve:

- Remove the obsolete per-file validate_local_pipe_references validator so
  qualified same-domain pipe refs (research.find_key_findings) resolve to a
  sibling-file declaration like bare refs do; missing refs are still caught
  post-merge by validate_pipe_library_with_libraries.
- Run validate_concept_references_in_blueprints on the concepts-only loader
  so a dangling concept_ref / item_concept_ref is rejected (pipelex
  structures / load_concepts_only), matching the full load.
- Route _load_single_dependency through LibraryCrateFactory so a multi-file
  dependency (PipeSignature header + concrete sibling) reconciles to the
  concrete instead of colliding in add_new_pipe and silently dropping a
  declaration; a genuine duplicate now raises.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
load_libraries_concepts_only loaded each discovered .mthds file as its own
one-file batch, so the cross-file concept-reference check ran before sibling
concepts were present — a valid additive concepts library could fail based on
directory load order. Batch all sibling files into a single
load_concepts_only_from_blueprints call, mirroring load_concepts_only_from_directory,
so same-domain references resolve against the merged set regardless of order.

Adds an order-independence regression test (referencing file sorts before its
declaration) and a CHANGELOG clause.

Reported by greptile on PR #970.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the phase/checkpoint planning narrative with a reviewer-facing
description of the feature: the four merge-time changes (signature/concrete
reconciliation, cross-file concept resolution, domain-metadata merge,
pending_signatures), the file map, error-surfacing, test coverage, design
decisions, and intentionally-deferred items. Points to wip/recursivity/ for
the deeper records.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lchoquel
Copy link
Copy Markdown
Member Author

lchoquel commented Jun 7, 2026

Review round 1 — addressed

greptile P1 (load_libraries_concepts_only one-file batches → order-dependent concept-ref validation): fixed in afd9217. load_libraries_concepts_only now collects all sibling .mthds files and runs a single load_concepts_only_from_blueprints batch — mirroring load_concepts_only_from_directory — so same-domain concept references resolve against the merged set regardless of directory load order. Added an order-independence regression test (test_load_concepts_only_library_dir_sibling_cross_reference, where the referencing file sorts before its declaration, so the old per-file loader would fail).

cubic: no issues found — thanks.

Also rewrote TODOS.md into a reviewer-facing guide describing the four merge-time changes, the file map, and the design decisions.

make agent-check clean, make agent-test green.

@greptileai @cubic-dev-ai please re-review.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Jun 7, 2026

Review round 1 — addressed

greptile P1 (load_libraries_concepts_only one-file batches → order-dependent concept-ref validation): fixed in afd9217. load_libraries_concepts_only now collects all sibling .mthds files and runs a single load_concepts_only_from_blueprints batch — mirroring load_concepts_only_from_directory — so same-domain concept references resolve against the merged set regardless of directory load order. Added an order-independence regression test (test_load_concepts_only_library_dir_sibling_cross_reference, where the referencing file sorts before its declaration, so the old per-file loader would fail).

cubic: no issues found — thanks.
...

@lchoquel I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 32 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="pipelex/builder/operations/validate_ops.py">

<violation number="1" location="pipelex/builder/operations/validate_ops.py:72">
P2: validate_all is missing pending_signatures in its return dict, inconsistent with the other three validation surfaces that now include it. The CLI JSON envelope for --all won't report pending signatures.</violation>
</file>

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

"bundle_path": str(bundle_path),
"validated_pipes": build_validated_pipes(result.dry_run_result),
"total_pipes": len(result.dry_run_result),
"pending_signatures": result.pending_signatures,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: validate_all is missing pending_signatures in its return dict, inconsistent with the other three validation surfaces that now include it. The CLI JSON envelope for --all won't report pending signatures.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At pipelex/builder/operations/validate_ops.py, line 72:

<comment>validate_all is missing pending_signatures in its return dict, inconsistent with the other three validation surfaces that now include it. The CLI JSON envelope for --all won't report pending signatures.</comment>

<file context>
@@ -69,6 +69,7 @@ async def validate_bundle_file(
         "bundle_path": str(bundle_path),
         "validated_pipes": build_validated_pipes(result.dry_run_result),
         "total_pipes": len(result.dry_run_result),
+        "pending_signatures": result.pending_signatures,
     }
 
</file context>

pending_signatures is a per-bundle, top-down-build nudge surfaced only by
`validate bundle` (as documented in agent_cli/CLAUDE.md). The validate-all sweep
is a whole-library check, not a build step, and acquire_and_validate tears its
library down before returning. Comment both validate-all surfaces so the
intentional asymmetry is recorded locally.

Addresses cubic P2 on PR #970 (intentional scoping, not a gap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lchoquel
Copy link
Copy Markdown
Member Author

lchoquel commented Jun 7, 2026

Review round 2 — addressed

cubic P2 (validate_all missing pending_signatures): intentional, not a gap — won't add it. pending_signatures is a per-bundle, top-down-build nudge ("which forward-declared headers are still unimplemented in this bundle"), surfaced only by validate bundle. This scoping is already documented in pipelex/cli/agent_cli/CLAUDE.md ("a non-blocking nudge on a successful lenient --allow-signatures run"). validate --all is a whole-library sweep, not a build step (and validate pipe omits it for the same reason). Adding it there would also force reshaping the shared acquire_and_validate, which tears its library down before returning. Recorded the rationale as a comment at both validate-all surfaces in f19277b so it isn't re-flagged.

greptile: 5/5, no blocking issues — thanks.

@greptileai @cubic-dev-ai please re-review.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Jun 7, 2026

Review round 2 — addressed

cubic P2 (validate_all missing pending_signatures): intentional, not a gap — won't add it. pending_signatures is a per-bundle, top-down-build nudge ("which forward-declared headers are still unimplemented in this bundle"), surfaced only by validate bundle. This scoping is already documented in pipelex/cli/agent_cli/CLAUDE.md ("a non-blocking nudge on a successful lenient --allow-signatures run"). validate --all is a whole-library sweep, not a build step (and validate pipe omits it for the same reason). Adding it there would also force reshaping the shared acquire_and_validate, which tears its library down before returning. Recorded the rationale as a comment at both validate-all surfaces in f19277b so it isn't re-flagged.

greptile: 5/5, no blocking issues — thanks.
...

@lchoquel I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 32 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="pipelex/builder/operations/validate_ops.py">

<violation number="1" location="pipelex/builder/operations/validate_ops.py:72">
P2: validate_all is missing pending_signatures in its return dict, inconsistent with the other three validation surfaces that now include it. The CLI JSON envelope for --all won't report pending signatures.</violation>
</file>

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread pipelex/libraries/concept_reference_validation.py Outdated
…ation

validate_concept_references_in_blueprints treated any concept ref whose local
code matched a native name as native (`ref.local_code in native_codes`), so a
same-domain qualified ref that merely shares a native local code (e.g.
`my_domain.Text`) was skipped instead of validated — suppressing the
undeclared-reference error even though that ref actually fails at resolution
(ConceptLibrary.get_required_concept_from_concept_ref_or_code uses the canonical
check). Switch to NativeConceptCode.is_native_concept_ref_or_code (bare `Text`
or `native.Text` only), matching resolution and contract_match. Adds a
regression test.

Reported by cubic on PR #970.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lchoquel
Copy link
Copy Markdown
Member Author

lchoquel commented Jun 7, 2026

Review round 3 — addressed

cubic P1 (concept_reference_validation.py:59 native check too broad): valid — fixed in f39ce6f. The check used ref.local_code in native_codes, so a same-domain qualified ref sharing a native local code (e.g. my_domain.Text) was wrongly treated as native and skipped, suppressing the undeclared-reference error — even though that ref actually fails at resolution (ConceptLibrary.get_required_concept_from_concept_ref_or_code uses the canonical check). Switched to NativeConceptCode.is_native_concept_ref_or_code (accepts only bare Text / native.Text), now consistent with both resolution and contract_match. Added a regression test (test_same_domain_qualified_ref_sharing_native_local_code_is_flagged).

Good catch. make agent-check clean, make agent-test green.

@greptileai @cubic-dev-ai please re-review.

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Jun 7, 2026

Review round 3 — addressed

cubic P1 (concept_reference_validation.py:59 native check too broad): valid — fixed in f39ce6f. The check used ref.local_code in native_codes, so a same-domain qualified ref sharing a native local code (e.g. my_domain.Text) was wrongly treated as native and skipped, suppressing the undeclared-reference error — even though that ref actually fails at resolution (ConceptLibrary.get_required_concept_from_concept_ref_or_code uses the canonical check). Switched to NativeConceptCode.is_native_concept_ref_or_code (accepts only bare Text / native.Text), now consistent with both resolution and contract_match. Added a regression test (test_same_domain_qualified_ref_sharing_native_local_code_is_flagged).

Good catch. make agent-check clean, make agent-test green.
...

@lchoquel I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 32 files

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

The pre-landing /review (independent adversarial + testing + maintainability
reviewers) found no bugs and verdict ship. Record the P3 polish it surfaced
(docstring accuracy, advisory-description silent-drop note, one low-confidence
test-coverage gap) in wip/recursivity/review-followups.md so they aren't lost,
and point TODOS.md at it. No production code change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lchoquel
Copy link
Copy Markdown
Member Author

lchoquel commented Jun 7, 2026

Pre-landing review (gstack /review) — verdict: ship

Ran an independent, fresh-context review pass on top of the bot rounds: three reviewers (adversarial / chaos-engineer, test-coverage, maintainability) each read the full diff against dev. (Cross-model Codex pass skipped — local service_tier config error, unrelated to this PR.)

Scope: CLEAN. Intent (additive multi-file libraries: reconciliation, cross-file concept resolution, domain-metadata merge, pending_signatures) matches the diff exactly — no scope creep, no missing requirements.

Correctness: no bugs found. The adversarial reviewer explicitly cleared the high-risk areas: the ConceptLibraryError/PipeLibraryErrorLibraryError reparenting doesn't shadow any other except arm (PipeNotFoundError re-raised first; PipeRunError/DryRunError/SignaturesNotAllowedError/PipeFactoryError/PipelexInterpreterError are not LibraryErrors); fingerprint is stable across load orders; load_from_crate ordering and the dependency path are sound; removing the per-file validators leaves no silent hole (dangling refs still caught at load/dry-run). Verdict: ship.

Tests: strong coverage. Reconciliation matrix, contract-match normalization (incl. the [] vs [1] / True == 1 guard), cross-batch + order-independent concepts-only resolution, domain-metadata merge matrix, error reparenting → structured ValidateBundleError, and pending_signatures content are all exercised.

Maintainability: clean, no over-engineering. The new modules (contract_match, collision_messages, domain_metadata_merge, concept_reference_validation) are small, single-purpose, pulled out at the right seams.

Only P3 polish surfaced (docstring accuracy, an advisory-description silent-drop note, one low-confidence test-coverage gap) — no bugs. Per "no over-engineering / defer doubts," these are recorded in wip/recursivity/review-followups.md rather than churned in now.

PR is ready to land once CI is green on the latest commit.

…signatures

Add reference-level docs-site coverage for the additive multi-file
capability shipped on this branch: a sibling-files note on
signature-pipes.md (a header file forward-declares signatures, definition
files supply the concrete pipes; they reconcile when contracts match), and
the new pending_signatures validate output on validate.md and agent-cli.md.

The full top-down multi-file walkthrough is deferred until the recursive
orchestrator (mthds-plugins) lands and pins the real workflow; tracked as
documentation debt on the PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant