Skip to content

feat: interface registry for cross-IU contract consistency#11

Open
Steve wants to merge 2 commits intochad:mainfrom
collectiveleap:feat/interface-registry
Open

feat: interface registry for cross-IU contract consistency#11
Steve wants to merge 2 commits intochad:mainfrom
collectiveleap:feat/interface-registry

Conversation

@Steve
Copy link
Copy Markdown

@Steve Steve commented May 1, 2026

Summary

  • Adds an interface registry — a single source of truth for how each IU is exposed at the architecture level (mount paths, resource field descriptions)
  • Eliminates mount path mismatches between IUs (e.g., web UI calling /todos when tasks are mounted at /tasks)
  • Post-processes LLM output to deterministically repair any fetch paths that don't match the registry

Problem

Two IUs that need to interact (Web Experience consuming the Tasks API) were generated independently with no shared contract. The mount path was derived separately in the scaffold generator and the prompt builder using the same heuristic — but the LLM could ignore the prompt instruction entirely and invent its own paths. This caused 404s at runtime.

Approach

The architecture target computes the interface registry from the IU plan — this is an internal compilation artifact, not a conservation layer. Both the scaffold (server.ts mount paths) and the prompt builder read from the same registry. A post-processing step in regen.ts rewrites any fetch() paths that don't match the registry using stem/synonym matching (todo→task, etc.).

Resource field descriptions are extracted from canonical "has" statements (e.g., "a project has a name and a color") and included in the prompt so consumer IUs know the provider's data shape.

Changes

  • src/scaffold.ts: New InterfaceEntry type, deriveInterfaces() function, extractResourceFields(). generateScaffold() uses registry for mount paths instead of inline derivation.
  • src/llm/prompt.ts: buildPrompt() accepts InterfaceEntry[] instead of string[]. Includes resource shape in sibling module context.
  • src/regen.ts: RegenContext carries interfaces. New repairFetchPaths() post-processor with resourceSimilarity() scoring.
  • src/cli.ts: Both bootstrap and regen compute deriveInterfaces() once and pass to RegenContext + scaffold.

Test plan

  • All 413 existing tests pass
  • Bootstrap on examples/todo-app generates correct mount paths in server.ts
  • Web UI fetch calls use /tasks and /projects (matching mount paths)
  • Web UI includes project creation (POST /projects) — resource fields in prompt give the LLM enough context
  • Fetch path repair correctly rewrites /todos/tasks when LLM ignores instructions
  • App runs and serves working UI at localhost:3000

🤖 Generated with Claude Code

Steve and others added 2 commits April 30, 2026 17:37
Users with a Claude Pro/Max subscription but no API key can now use
Phoenix code generation via the `claude` CLI. The provider auto-detects
when the CLI is available and falls back to it when no ANTHROPIC_API_KEY
or OPENAI_API_KEY is set.

- New `ClaudeCliProvider` in `src/llm/claude-cli.ts` pipes prompts via
  stdin to `claude -p` with `--system-prompt` for system messages
- Provider resolution auto-detects `claude` CLI as third-priority fallback
- Also adds missing `@types/node` dev dependency needed for build

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
IUs that depend on each other (e.g., Web Experience calling the Tasks API)
previously derived mount paths independently in the scaffold and prompt
builder, leading to mismatches like /todos vs /tasks. The LLM could also
ignore path instructions entirely.

This adds an interface registry — a single source of truth for how each
IU is exposed at the architecture level:

- New `InterfaceEntry` type and `deriveInterfaces()` in scaffold.ts,
  computed from the IU plan and canonical nodes
- Resource field descriptions extracted from canonical "has" statements
  so consumer IUs know the provider's data shape
- Both scaffold (server.ts mount paths) and prompt builder read from
  the same registry instead of deriving paths independently
- Post-processing step in regen.ts rewrites any fetch() paths that
  don't match the registry, using stem/synonym matching
- Claude CLI provider timeout increased to 10 minutes for large UIs

Co-Authored-By: Claude Opus 4.6 (1M context) <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