Skip to content

feat(api+spawn): DPLAN-0133 Phase 1 (part 2/2) + Phase 2 — bridge registry, driver auto-discovery, integrations handlers#290

Open
AIOSAI wants to merge 7 commits intomainfrom
feat/dplan-0133-integrations-template
Open

feat(api+spawn): DPLAN-0133 Phase 1 (part 2/2) + Phase 2 — bridge registry, driver auto-discovery, integrations handlers#290
AIOSAI wants to merge 7 commits intomainfrom
feat/dplan-0133-integrations-template

Conversation

@AIOSAI
Copy link
Copy Markdown
Owner

@AIOSAI AIOSAI commented Apr 15, 2026

Summary

Phase 1 (part 2/2) — spawn template scaffold

  • Adds apps/integrations/README.md to the builder template so every branch spawned with drone @spawn create automatically gets the private integration scaffold introduced in DPLAN-0133.
  • Template registry regenerated: 44 → 45 files, 23 → 24 directories.
  • New test in test_citizen_classes.py asserts apps/integrations/README.md exists after _spawn_agent().

Phase 2 — @api driver registry + generic contract system

  • bridge.py — module-level dict registry (register/resolve/list_contracts/clear); zero side-effects on import
  • registry.pyload_drivers() walks apps/integrations/*/driver.py via importlib; handles empty dirs, missing driver.py, and broken imports gracefully (logs WARNING, skips, no crash); idempotent via _loaded flag
  • integrations_manager.py — auto-discovered module routing drone @api integrations list and drone @api integrations call <contract> [args...]
  • handlers/integrations/list.py + call.py — thin handler layer (log + return result dicts)
  • apps/integrations/testcontract/driver.py — canary driver (gitignored); registers "test""pong"
  • tests/test_integrations.py — 17 new tests (bridge CRUD, registry walk, fetch_contracts, call_contract)

Test plan

  • drone @api integrations list with empty apps/integrations/ → "No integrations configured", exit 0
  • drone @api integrations list on this branch → shows test (canary driver)
  • drone @api integrations call test → prints pong, exit 0
  • drone @api integrations call nope → error message, exit 1
  • python -m pytest src/aipass/api/tests/ — 306 existing + 17 new = 323 passed, zero regressions
  • python -m pytest src/aipass/spawn/tests/ — 215 passed, 37 skipped

Do not merge — user reviewing end of day.

🤖 Generated with Claude Code

AIOSAI and others added 5 commits April 15, 2026 15:16
…e timeout for long-running poller

Co-Authored-By: @drone <drone@aipass>
… --rebase to prevent dirty-tree abort

Co-Authored-By: @drone <drone@aipass>
…pps/integrations/** with README negation, plus scaffold README.md in all 10 core branches' apps/integrations/ — private integration space is now leak-proof by construction. Drivers and wrappers dropped here stay local; only README.md is tracked. See DPLAN-0133 for architecture rationale (three-layer design: @api drivers, per-branch wrappers, public generic contracts).

Co-Authored-By: @devpulse <devpulse@aipass>
…affold to builder template

Every new branch spawned via `drone @Spawn create` now lands with
`apps/integrations/README.md` — the private integration space introduced
in DPLAN-0133. The README explains the three-layer architecture (api
driver → branch wrapper → public contracts) and is the only tracked file
in the folder; everything else dropped there is gitignored by the root
rule shipped in PR #289.

Changes:
- templates/builder/apps/integrations/README.md — new scaffold file
- templates/builder/.spawn/.template_registry.json — regenerated (44→45 files, 23→24 dirs)
- tests/test_citizen_classes.py — new test asserting integrations/ exists after create; added missing docstrings to 14 test methods
- .seedgo/bypass.json — added architecture + encapsulation bypasses for test_citizen_classes.py (standard test-file exemptions)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@AIOSAI
Copy link
Copy Markdown
Owner Author

AIOSAI commented Apr 15, 2026

PR overlap map (all three PRs touch overlapping files via drone @git system-pr backlog scoop):

PR #290 is a strict superset of both #288 and #289. Merging #290 alone delivers all three sets of changes. Recommended merge strategy: close #288 and #289 as superseded by #290, then merge #290. OR merge in order #288#289#290 and accept that each will be partially redundant on top of the prior.

No conflicts between the three — they all modify the same content to the same end state. Pure backlog scoop artifact. — devpulse

…o-discovery + integrations handlers

Implements the @api side of the three-layer private-integration architecture
(DPLAN-0133). Branches call generic contracts; @api resolves them at runtime
to whatever private driver is registered locally.

New modules:
  apps/modules/bridge.py             — module-level dict registry (register/resolve/list_contracts/clear)
  apps/modules/registry.py           — auto-discovery walker for apps/integrations/*/driver.py
  apps/modules/integrations_manager.py — drone @api integrations {list,call} command routing
  apps/handlers/integrations/list.py — handler: log + return contract listing
  apps/handlers/integrations/call.py — handler: invoke driver, return result dict
  apps/integrations/testcontract/driver.py — canary driver (contract "test" → "pong", gitignored)
  tests/test_integrations.py         — 17 tests (bridge, registry, fetch_contracts, call_contract)

All 306 existing tests remain green. Empty integrations/ exits 0 cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@AIOSAI AIOSAI changed the title feat(spawn): DPLAN-0133 Phase 1 part 2/2 — add apps/integrations/ to builder template feat(api+spawn): DPLAN-0133 Phase 1 (part 2/2) + Phase 2 — bridge registry, driver auto-discovery, integrations handlers Apr 15, 2026
@AIOSAI
Copy link
Copy Markdown
Owner Author

AIOSAI commented Apr 15, 2026

@api just pushed Phase 2 onto this branch. PR #290 is now the complete DPLAN-0133 Phase 1 + Phase 2 delivery (+1411 -9).

Full PR #290 contents:

Acceptance per @api's reply:

  • drone @api integrations list (empty) → 'No integrations configured.', exit 0 ✓
  • drone @api integrations list (this branch) → shows 'test' ✓
  • drone @api integrations call test → 'pong', exit 0 ✓
  • drone @api integrations call nope → error + exit 1 ✓

One design note from @api: handlers can't import bridge directly per seedgo's cli/handlers rule, so they went with module-layer orchestration — integrations_manager.py calls bridge and passes data to handlers. Public API surface is fetch_contracts() and call_contract() on integrations_manager.

Merge strategy: PR #290 is now the strict superset of #288 and #289 AND Phase 2. Merging #290 alone delivers everything. Close #288 and #289 as superseded. — devpulse

…bled Try: prefix

Found via stress testing DPLAN-0133 Phase 2:
- `drone @api integrations foobar` returned exit 0 (success) instead of 1
- Error message showed "Try: Try: list, call" (doubled prefix)

Two-line fix: suggestion string drops "Try:" prefix (error() adds it),
return True → sys.exit(1) for proper non-zero exit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AIOSAI
Copy link
Copy Markdown
Owner Author

AIOSAI commented Apr 16, 2026

Stress test complete — 2 bugs found and fixed (pushed to this branch)

Tested with 4 test drivers: multi-contract (memory/search/explode), broken import, no register() hook, empty folder.

Bug 1 (fixed, commit 5ab2a99): drone @api integrations foobar exited 0 instead of 1 — unknown subcommands weren't calling sys.exit(1). Now exits non-zero properly.

Bug 2 (fixed, same commit): Error message showed 'Try: Try: list, call' — doubled prefix because error() already adds '→ Try:' and the suggestion string also started with 'Try:'. Removed the duplicate from the suggestion.

What passed clean (no bugs):

  • Multi-contract driver registering 3 contracts from one driver.py ✓
  • Args forwarding through bridge to driver functions ✓
  • Complex return types (strings, dicts) printed correctly ✓
  • Driver that raises RuntimeError — caught cleanly, error message shown, exit 1 ✓
  • Broken driver (import error) — skipped by registry walker, logged warning, other drivers loaded fine ✓
  • Driver without register() hook — loaded without crash ✓
  • Empty folder (no driver.py) — skipped silently ✓
  • All test drivers correctly gitignored by the repo-root rule ✓
  • 17/17 @api tests pass after fix

Verdict: Phase 2 is solid. Two minor bugs in error handling, now fixed. Core architecture (bridge registry, auto-discovery, contract dispatch) works correctly under stress. — devpulse

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