Skip to content

fix(orchestrator): agentic LLM decompose + capability matching (composition keystone, #133) - #151

Open
LamaSu wants to merge 5 commits into
masterfrom
fix/compose-keystone-133
Open

fix(orchestrator): agentic LLM decompose + capability matching (composition keystone, #133)#151
LamaSu wants to merge 5 commits into
masterfrom
fix/compose-keystone-133

Conversation

@LamaSu

@LamaSu LamaSu commented Jun 15, 2026

Copy link
Copy Markdown
Owner

What & why

POST /api/requests/{id}/decompose was hardcoded to a document-printing + logistics
template and ignored the natural-language goal. "a 12-inch margherita pizza made and
delivered to me in Manhattan" produced [doc-prep, printing, courier-pickup, delivery],
evidenceRequirements=['pdf_proof'], budget=1000, and zero capability matches.

This makes decompose agentic (LLM-driven, with a deterministic offline fallback) and
grounds every node to a registered capability via semantic search — the composition
keystone (coord bulletin #133).

How

  • services/agentic-decomposer.ts (new): a pure, dependency-injected engine.
    1. Plan the steps with an LLM (lazy @anthropic-ai/sdk, degrades to an offline
      heuristic when no ANTHROPIC_API_KEY).
    2. Match each step to a registered capability via token-overlap semantic search
      over the live registry (CapabilityFacade).
    3. Derive the budget from the matched caps' prices and the evidence requirements
      from each matched cap's domain + assurance tier.
      Legacy keyword templates are used only when neither an LLM nor any capability
      grounded the plan — so a non-document goal can never become a document DAG.
  • services/request-decomposer.ts: print_deliver now requires a real
    document/print signal — generic "deliver/courier/mail/ship" no longer selects the
    document template (the feat(dashboard): living substrate visualizer — generative topology #133 root cause). Exposes calculateCriticalPath.
  • routes/requests.ts: POST /api/requests and /decompose run the agentic
    engine, leave the request decomposed (publishing stays the explicit /publish
    step — no auto-publish), and derive the budget from matched prices instead of the
    hardcoded 1000. critical-path is computed from the stored DAG (no re-decompose).
  • spec: +"decomposed" request status; per-node matchStatus /
    matchedCapabilityId / matchedKernelId / matchScore; DecompositionResult
    derivedBudget / matchedCount / usedLLM / usedFallback.

Acceptance

  • ✅ "Margherita pizza delivered to Manhattan" → make-pizza node matched to
    Marios Pizzeria wood-fired-pizza
    + delivery node matched to Daves Delivery
    local-courier-delivery
    .
  • ✅ Budget derived from matched prices (12 + 6 = 18 USDC), not 1000.
  • evidenceRequirements from the matched cap (e.g. photo_of_completed_item,
    delivery_confirmation), never pdf_proof.
  • ✅ Decompose does not auto-publish (status: "decomposed").
  • ✅ A non-printing goal never yields a document-printing DAG (proven at the engine,
    the template-detection, and the route layers).

Tests

  • __tests__/agentic-decomposer.test.ts (new, 14 tests): pure-engine acceptance with
    injected stub LLM + matcher (no network), plus matcher / heuristic / parser units.
  • __tests__/requests.test.ts: route integration seeds the two caps and asserts the
    full pizza flow; legacy expectations updated (decomposed status; the HPLC request
    now matches a registered hplc capability).
  • Full gateway suite: 1643 passed / 4 skipped / 0 failed. Workspace typecheck: 80/80.

Do not merge or deploy from this PR (both are gated).

🤖 Generated with Claude Code

LamaSu and others added 5 commits June 15, 2026 13:32
…elds (#133)

Adds the resting state after decompose (not auto-published) and the per-node
matchStatus/matchedCapabilityId/matchedKernelId/matchScore fields plus
DecompositionResult.derivedBudget/matchedCount/usedLLM/usedFallback so a
decomposition can be priced and evidenced from the matched capabilities.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cher (#133)

Pure, dependency-injected engine: LLM planner (lazy Anthropic, degrades to an
offline heuristic without a key) -> semantic match each step to a registered
capability -> derive budget from matched prices and evidence from the matched
cap's domain+tier. Legacy templates are used only when neither an LLM nor any
match grounded the plan, so a non-document goal can never become a doc DAG.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…133)

Generic delivery words (deliver/courier/mail/ship) no longer select the
document print+logistics template — the #133 root cause. Also defaults
matchStatus='none' on legacy nodes and exports calculateCriticalPath.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s routes; no auto-publish (#133)

POST /api/requests and /decompose now run the agentic engine, leave the request
'decomposed' (publishing stays the explicit /publish step), and derive the
budget from matched capability prices instead of the hardcoded 1000 default.
critical-path is computed from the stored DAG rather than re-decomposing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… units (#133)

Pure-engine acceptance: 'margherita pizza delivered to Manhattan' -> make(Marios
wood-fired-pizza) + delivery(Daves local-courier-delivery), budget 18 derived,
evidence from caps (not pdf_proof), never published, never a document DAG.
Route integration seeds the two caps and asserts the same end-to-end. Updates
legacy expectations (decomposed status, HPLC now matches a registered hplc cap).

Co-Authored-By: Claude Opus 4.8 (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