Commit Graph

7 Commits

Author SHA1 Message Date
Harsh Batheja f48c939d9b feat: lifecycle manager, backlog auto-claim, task decomposition, and verification gate (#365)
* feat: wire lifecycle manager, backlog auto-claim, and dashboard overhaul

- Start LifecycleManager in dashboard server (30s polling) so reactions
  actually fire: CI failures, review comments, merge conflicts are now
  auto-forwarded to agents
- Add backlog auto-claim poller (60s interval) that watches for issues
  labeled `agent:backlog` and auto-spawns agent sessions up to max
  concurrent limit (5)
- Add tabbed dashboard UI: Board (kanban), Backlog (issue queue), PRs
- Add issue creation form in dashboard — creates GitHub issues with
  `agent:backlog` label for immediate agent pickup
- Add API routes: /api/backlog, /api/issues, /api/setup-labels
- Pass notifier config through plugin registry (slack webhook fix)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add task decomposition layer (classify → decompose → recurse)

Adds LLM-driven recursive task decomposition upstream of session spawning.
Complex issues are broken into atomic subtasks before agents start working.
Each agent receives lineage context (where it fits in the hierarchy) and
sibling awareness (what parallel agents are doing).

Core changes:
- New decomposer module (core/src/decomposer.ts) — classify, decompose,
  plan tree, lineage formatting, using Claude API
- Extended SessionSpawnConfig with lineage/siblings fields
- Prompt builder Layer 4: decomposition context (hierarchy + siblings)
- ProjectConfig.decomposer config section with Zod validation
- Tracker plugin: added removeLabels support for label management

CLI:
- `ao spawn <project> <issue> --decompose` flag
- `--max-depth <n>` option for decomposition depth
- Spawns multiple sessions with lineage context for composite tasks

Backlog poller:
- Respects project.decomposer.enabled for auto-decomposition
- Posts plan as issue comment when requireApproval=true
- Auto-spawns subtasks with lineage when requireApproval=false

Config example:
  projects:
    my-app:
      decomposer:
        enabled: true
        maxDepth: 3
        requireApproval: true

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add verification gate — issues stay open until human confirms fix

PR merge no longer auto-closes GitHub issues. Instead:

1. On PR merge: issue labeled `merged-unverified`, stays open
2. Human checks staging, then runs `ao verify <issue>` to close
3. Or `ao verify <issue> --fail` to flag verification failure

Changes:
- services.ts: labelIssuesForVerification() replaces closeIssuesForMergedSessions()
- New CLI command: `ao verify` (verify/fail/list modes)
- New API route: GET/POST /api/verify
- Dashboard: new Verify tab with one-click verify/fail buttons
- ao status: shows count of issues awaiting verification
- Idle session detection + auto-nudge reaction
- Use TERMINAL_STATUSES in batch-spawn dedup check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: rename decomposerConfig to avoid variable shadowing

Addresses Bugbot medium severity issue where inner  variable
shadowed outer  from getServices().

* fix: update pnpm-lock.yaml for new @anthropic-ai/sdk dependency

* fix: resolve remaining merge conflicts and syntax errors

- Remove leftover conflict markers in types.ts
- Remove orphaned code in services.ts
- Fix semicolon to comma in config.ts
- Remove unused import in verify.ts

* fix: address final Bugbot issues

- requireApproval path now exits early with continue to prevent
  fall-through to in-progress label and session spawned comment
- remove packages/core/package-lock.json (pnpm workspace should only
  use root pnpm-lock.yaml)

* fix: idle sessions now transition back to working

When agent resumes activity after being idle, the status correctly
transitions to 'working' instead of remaining stuck in 'idle' state.

* fix(backlog): remove agent:backlog label when claiming issues

When claiming issues from the backlog, the poller now removes the
agent:backlog label in addition to adding agent:in-progress. This
prevents duplicate work if all spawned sessions reach terminal status
and the poller rediscovers the issue.

* fix(test): use Set for TERMINAL_STATUSES mock

The mock for TERMINAL_STATUSES was an array, but the real export is a
ReadonlySet. Changed to use a Set so tests with non-empty sessions won't
crash when calling .has().

* fix(web): resolve backlog/dashboard regressions after branch sync

* fix(web): align dashboard events hook and SSE test mocks

* fix(notifier-openclaw): apply exponential delay from retry index

* fix(integration-tests): align openclaw retry delay expectation

* fix(web): keep dashboard header stats in sync

* fix(openclaw): keep first retry at base delay

---------

Co-authored-by: Agent <agent@example.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Harsh <harsh@Ubuntu-24-Forrest.lan>
Co-authored-by: Harsh <harsh@example.com>
2026-03-11 06:41:03 +00:00
prateek 1521c0732c feat(ao): add OpenClaw notifier plugin for AO escalations
Adds AO notifier-openclaw (webhook-first Phase 0), registry wiring, tests, docs, and BugBot fixes.
2026-03-11 06:41:03 +00:00
Harsh Batheja 4e2144d99e
feat: OpenCode session lifecycle and CLI controls (#315)
* feat: refine OpenCode session reuse strategy and cleanup

* fix: harden OpenCode session selection and lint errors

* refactor: centralize OpenCode reuse resolution flow

* fix: return 404 for missing session in message route

* feat: replace force remap with terminal reload control

* fix: protect project path from session kill cleanup

* fix: preserve fullscreen alignment without reload action

* fix: harden OpenCode session id handling and title reuse selection

* fix: show OpenCode reload control and remap before restart

* fix: preserve title-only OpenCode reuse with fallback mapping persistence

* fix: resolve remaining PR315 Bugbot findings

* fix: keep OpenCode discovery title-based without timestamp sorting

* fix: avoid enrichment race fallout in session listing

* fix: guard OpenCode discovery parse with array check

* fix: stabilize Linear comment integration check

* fix: harden OpenCode discovery and prompt option flow

* ux: clarify OpenCode terminal restart action

* fix: remap OpenCode session fresh on each restart

* fix: validate remap session ids before reuse

* fix: clean archived metadata only after purge

* docs: align OpenCode remap selection with title-based behavior

* fix: harden opencode cleanup and ignore local sisyphus state

* test: add timeout cleanup coverage for session enrichment

* fix: harden Linear integration helper against transient non-JSON errors

* fix: make linear integration assertions resilient to eventual consistency

* fix: remove unused fs import after rebase

* fix: address remaining Bugbot blockers for opencode session handling

* fix: avoid stale metadata overwrite during restore post-launch

* fix: forward subagent in orchestrator flows and defer reuse lookup

* fix: apply configured subagent fallback for session spawn

* fix: scope archived cleanup by project and delay archive restore write

* fix: normalize orchestrator strategy aliases in start display logic

* fix: centralize orchestrator strategy normalization in core

* fix: derive orchestrator reuse display from spawn result

* fix: keep cleanup results consistent across project-id collisions

* fix: namespace cleanup results when session IDs collide

* fix: harden GitHub issue stateReason fallback

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: avoid false failing CI state mapping

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: add tmux command timeouts

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: bound session API enrichment latency

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: repair scm-github merge resolution

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: repair lifecycle-manager test merge

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: delay archive metadata recreation until restore passes

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test: restore claim-pr session mocks

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix: address review findings for OpenCode lifecycle PR

- Fix stripControlChars to preserve newlines for reload commands
- Add SessionNotFoundError and use instanceof checks in API routes
- Document orchestratorSessionStrategy in YAML example
- Validate existingSessionId with asValidOpenCodeSessionId()
- Extract inline Node script to buildSessionLookupScript helper
- Create OpenCodeSessionManager interface for remap capability
- Create OpenCodeAgentConfig type for agent-specific config
- Change default orchestratorSessionStrategy from delete to reuse

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: guard reused session display without metadata

* chore: add agent config files to .gitignore

Agent configuration files (CLAUDE.md, AGENTS.md, IMPROVEMENTS.md, etc.) are personal and project-specific. They should not be committed to the repository.

Changes:
- Remove CLAUDE.md from git tracking
- Add agent config files to .gitignore
- Create .gitignore-template for reference

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore: update gitignore for agent config folder structure

Reorganized agent configuration files:
- CLAUDE.md and AGENTS.md stay in root (agents read them there)
- Tracking files move to .opencode/ (IMPROVEMENTS.md, etc.)
- Optional Claude files in .claude/

Updated .gitignore to ignore folders instead of individual files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: tighten opencode remap and session discovery safeguards

* fix: address Bugbot findings in session manager

* fix: scope opencode discovery to opencode sessions

* fix: restore concurrent listing and strict permission literals

* fix: throw SessionNotFoundError, parallelize list enrichment, fix permissions type

- Session manager now throws SessionNotFoundError instead of plain Error
  for missing sessions, so web API routes correctly return 404 (not 500)
- Parallelize session enrichment in list() — was sequential, causing O(N)
  latency for N sessions with subprocess enrichment
- Fix AgentLaunchConfig.permissions type to accept legacy "skip" value
  (AgentPermissionInput instead of AgentPermissionMode)
- Add happy-path and validation tests for /api/sessions/:id/message route
- Update all test mocks to use SessionNotFoundError

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: route ao send through session manager

* feat: add purge option to orchestrator stop

* fix: register opencode agent in web services

* test: align web API missing-session coverage

* fix: match notifier config by plugin name

* refactor: dedupe session lookup and tmux buffer send flow

* test: update send lifecycle wait expectation

* fix: harden send routing and cleanup purge controls

---------

Co-authored-by: Harsh <harsh@Ubuntu-24-Forrest.lan>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Prateek <karnalprateek@gmail.com>
2026-03-08 09:55:44 +05:30
prateek 21335db8af
feat: publish to npm under @composio scope (#32)
* feat: add npm publishing support with @composio scope

Set up Changesets for version management, add publish metadata to all 20
packages under the @composio scope, create an unscoped wrapper package
(@composio/agent-orchestrator) for global install, and add a GitHub
Actions release workflow.

- Rename all packages from @agent-orchestrator/* to @composio/ao-*
- Add @composio/agent-orchestrator wrapper (bin shim → @composio/ao-cli)
- Add license, repository, homepage, bugs, files, engines to all packages
- Add .npmrc (access=public), MIT LICENSE file
- Add .changeset/ config with linked versioning for all packages
- Add .github/workflows/release.yml (changesets publish CI)
- Add changeset, version-packages, release scripts to root

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: exclude private web package from release build

The release script now filters out @composio/ao-web, matching the
workflow's existing exclusion and preventing a Next.js build failure
from blocking npm publishing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-15 04:28:57 +05:30
prateek 8707faf11c
feat: implement SCM and tracker plugins (github, linear) (#4)
* feat: implement SCM and tracker plugins (github, linear)

Implement three plugin interfaces from packages/core/src/types.ts:

- scm-github: Full GitHub PR lifecycle via `gh` CLI — PR detection by
  branch, state tracking, CI checks, reviews, review decision, pending
  comments, automated bot comment detection (cursor[bot], codecov, etc.),
  and merge readiness (CI + reviews + conflicts + draft).

- tracker-github: GitHub Issues tracker via `gh` CLI — issue CRUD,
  completion check, branch naming (feat/issue-N), prompt generation,
  list/filter/update/create with label and assignee support.

- tracker-linear: Linear issue tracker via GraphQL API (LINEAR_API_KEY) —
  issue fetch, completion check, branch naming (feat/IDENTIFIER), prompt
  generation, list with team/state/label filters, state transitions via
  workflow state resolution, issue creation with teamId config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review — GraphQL injection, N+1 queries, timeouts, tests

- tracker-linear: use GraphQL variables in listIssues to prevent injection
- tracker-linear: add 30s HTTP timeout to linearQuery
- tracker-linear: fix issueUrl to use workspace slug from project config
- tracker-linear: add labels/assignee support to createIssue
- scm-github: rewrite getPendingComments to use GraphQL reviewThreads
  with real isResolved status instead of hardcoding false
- scm-github: simplify getAutomatedComments to single API call (N+1 fix)
- scm-github: add 30s timeout to gh CLI calls
- scm-github: fix parseDate to return epoch instead of fabricating dates
- scm-github: add repo format validation in detectPR
- scm-github: fix getCISummary to not count all-skipped as passing
- tracker-github: add 30s timeout to gh CLI calls
- tracker-github: fix createIssue to not use unsupported --json flag
- Add comprehensive vitest tests for scm-github and tracker-github

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Codex review — assignee lookup, GraphQL vars, status checks

Iteration 1 fixes (8 issues from Codex review):
- tracker-linear: remove invalid assigneeDisplayName, resolve assignee
  by display name to ID via users query after creation
- tracker-linear: add HTTP status code check in linearQuery
- tracker-linear: throw on missing workflow state in updateIssue
- scm-github: use GraphQL variables ($owner, $name, $number) in
  getPendingComments instead of string interpolation
- scm-github: guard against empty comment nodes in review threads
- scm-github: use mergeStateStatus in getMergeability (BEHIND, BLOCKED)
- tracker-github: default description to "" in createIssue

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review + lint — error context, GraphQL vars, mergeability

- scm-github/tracker-github: wrap gh() errors with command context + cause
- scm-github: use GraphQL variables ($owner, $name, $number) in
  getPendingComments to prevent injection
- scm-github: guard against empty review thread nodes
- scm-github: incorporate mergeStateStatus (BEHIND/BLOCKED) in getMergeability
- tracker-linear: add identifier vs UUID comment in updateIssue
- Fix ESLint preserve-caught-error violations
- Remove unused mockGhRaw in scm-github tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add pagination to getAutomatedComments and increase thread limit

- getAutomatedComments: add --paginate flag to REST API call to fetch
  all review comments beyond the default 30-item first page
- getPendingComments: increase GraphQL reviewThreads limit from 100 to
  250 (GitHub's max for connections)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use per_page=100 instead of --paginate for JSON-safe pagination

Replace --paginate with -F per_page=100 in getAutomatedComments to
avoid concatenated JSON arrays that break JSON.parse on multi-page
responses. 100 is GitHub's max per_page value.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: filter out resolved threads in getPendingComments

The method name implies it should only return unresolved/pending review
threads. The isResolved data was already fetched via GraphQL but was not
being filtered on, causing resolved threads to be included in results.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add comprehensive tracker-linear test suite (53 tests)

Covers all Tracker interface methods: getIssue, isCompleted, issueUrl,
branchName, generatePrompt, listIssues, updateIssue, createIssue.
Mocks node:https request to simulate Linear GraphQL API responses.
Tests state mapping, error handling, assignee/label resolution, and
GraphQL variable injection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address 6 bugbot review comments on PR #4

- GraphQL reviewThreads(first: 250) → first: 100 (GitHub max)
- noConflicts false when mergeable is UNKNOWN (not just CONFLICTING)
- updateIssue now handles labels and assignee (not just state/comment)
- Add res.on("error") handler in linearQuery to prevent crashes
- createIssue returns only actually-applied labels, not all requested
- Tests added/updated for all fixes (144 total across 3 plugins)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: make Linear updateIssue labels additive to match GitHub behavior

Linear's issueUpdate replaces all labels, while GitHub's --add-label is
additive. Now fetches existing label IDs first and merges with new ones
before sending to issueUpdate, ensuring consistent behavior across both
tracker implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: default listIssues to open state in tracker-linear

When no state filter is specified, tracker-github defaults to "open"
but tracker-linear was returning all issues. Now defaults to excluding
completed/canceled issues, matching tracker-github behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add Composio SDK support to tracker-linear

Allow users with a COMPOSIO_API_KEY to use the Linear tracker without
a separate LINEAR_API_KEY. The plugin auto-detects which key is available
and routes through either the direct Linear GraphQL API or Composio's
LINEAR_RUN_QUERY_OR_MUTATION tool. All existing queries and response
parsing are reused via a GraphQLTransport abstraction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address 2 bugbot review comments on PR #4

1. getCIChecks now throws on error instead of silently returning [],
   preventing a fail-open where CI appears healthy when we can't fetch
   check status. getCISummary catches the error and returns "failing".

2. Handle GitHub's UNSTABLE mergeStateStatus (required checks failing)
   as a merge blocker in getMergeability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: prevent unhandled promise rejection in Composio timeout race

When the timeout wins Promise.race in the Composio transport, the
resultPromise is left without a rejection handler. If the SDK call
later rejects, it becomes an unhandled promise rejection that crashes
Node.js 20+ with --unhandled-rejections=throw.

Attach no-op .catch() to both resultPromise and timeoutPromise before
the race so whichever promise loses has its rejection silently handled.

Also adds plugin integration tests (core -> real plugins -> mocked gh CLI).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: chain error cause in getCIChecks and fix core build

- getCIChecks catch now preserves the original error via { cause: err }
  instead of discarding it, matching the pattern used by the gh() helper
- Add tsconfig.build.json to core that excludes __tests__/ from build
  compilation, preventing TS5055 errors from circular workspace deps
  (integration tests import plugin packages that depend back on core)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove circular devDeps, address bugbot comments

- Remove plugin devDependencies from core/package.json that created a
  circular dependency (core -> plugins -> core), breaking CI build order
- Document in_progress state as intentional no-op in tracker-github
  updateIssue (GitHub Issues only supports open/closed)
- Remove @composio/core optional peerDependency from tracker-linear;
  the dynamic import() already handles the missing package gracefully,
  and the peer dep was pulling composio + transitive deps into lockfile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add real integration test for tracker-linear against Linear API

Creates a test that exercises the full tracker-linear plugin lifecycle
against the real Linear API — createIssue, getIssue, isCompleted,
listIssues, updateIssue (comment, close, reopen), generatePrompt,
branchName, issueUrl. Each run creates a throwaway test issue and
trashes it in cleanup. Skipped when LINEAR_API_KEY is not set.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* ci: pass LINEAR_API_KEY and LINEAR_TEAM_ID to integration tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: support both LINEAR_API_KEY and COMPOSIO_API_KEY in integration test

The tracker-linear integration test now runs with either credential:
- LINEAR_API_KEY: direct Linear API (full cleanup via trash)
- COMPOSIO_API_KEY: via Composio SDK (cleanup falls back to closing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: don't pass COMPOSIO_API_KEY to CI integration tests

When both LINEAR_API_KEY and COMPOSIO_API_KEY are set, the plugin
prefers the Composio transport which requires @composio/core SDK.
The SDK isn't installed in CI, so use the direct LINEAR_API_KEY
transport which has no extra dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use import.meta.url in vitest config, default createIssue description

- Replace __dirname with import.meta.url-derived dirname in ESM config
- Default createIssue description to "" for defensive safety

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: map CANCELLED and ACTION_REQUIRED CI conclusions to failed

Terminal check conclusions (CANCELLED, ACTION_REQUIRED) were falling
through to "pending", causing the lifecycle manager to wait forever.
Also changed the default else branch to "failed" (fail-closed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 15:45:51 +05:30
Prateek 2b9a28a031 test: add comprehensive unit tests for all core services
Add vitest test suite with 103 tests across 5 test files:

- metadata.test.ts (19 tests): read/write/update/delete/list, key=value
  parsing, comments, values with equals signs, archiving, dotfile exclusion
- event-bus.test.ts (22 tests): emit/on/off, wildcard listeners, handler
  error resilience, priority inference, JSONL persistence round-trip,
  filtered history with sessionId/projectId/type/priority/since/limit
- tmux.test.ts (23 tests): all tmux wrappers with mocked child_process,
  session listing/parsing, send-keys short vs load-buffer long text,
  capture-pane, kill, getPaneTTY
- session-manager.test.ts (23 tests): spawn pipeline with mocked plugins,
  session numbering, branch derivation, event emission, metadata writing,
  list with dead runtime detection, kill with cleanup, send via runtime
- lifecycle-manager.test.ts (16 tests): state transitions (spawning→working,
  killed, stuck, needs_input, ci_failed, merged, mergeable), reaction
  triggering, auto=false suppression, on/off handlers, getStates isolation

Also fixes inferPriority to handle merge.completed as "action" priority.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 18:42:45 +05:30
Prateek 5058c409d5 feat: scaffold TypeScript monorepo with all plugin interfaces
Phase 0 complete. Establishes:
- pnpm workspace with 18 packages (core, cli, web, 15 plugins)
- Complete type definitions in packages/core/src/types.ts defining
  all 8 plugin slot interfaces (Runtime, Agent, Workspace, Tracker,
  SCM, Notifier, Terminal) + core service interfaces
- YAML config loader with Zod validation and sensible defaults
- Plugin registry with built-in discovery
- CLAUDE.md with conventions for spawned agents

All agents can now branch from main and implement their assigned
packages against the interfaces defined in types.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:02:42 +05:30