Files
stack/docs/tasks/WP2-macp-package.md
Mos (Agent) 10689a30d2
Some checks failed
ci/woodpecker/push/ci Pipeline failed
ci/woodpecker/pr/ci Pipeline failed
feat: monorepo consolidation — forge pipeline, MACP protocol, framework plugin, profiles/guides/skills
Work packages completed:
- WP1: packages/forge — pipeline runner, stage adapter, board tasks, brief classifier,
  persona loader with project-level overrides. 89 tests, 95.62% coverage.
- WP2: packages/macp — credential resolver, gate runner, event emitter, protocol types.
  65 tests, 96.24% coverage. Full Python-to-TS port preserving all behavior.
- WP3: plugins/mosaic-framework — OC rails injection plugin (before_agent_start +
  subagent_spawning hooks for Mosaic contract enforcement).
- WP4: profiles/ (domains, tech-stacks, workflows), guides/ (17 docs),
  skills/ (5 universal skills), forge pipeline assets (48 markdown files).

Board deliberation: docs/reviews/consolidation-board-memo.md
Brief: briefs/monorepo-consolidation.md

Consolidates mosaic/stack (forge, MACP, bootstrap framework) into mosaic/mosaic-stack.
154 new tests total. Zero Python — all TypeScript/ESM.
2026-03-30 19:43:24 +00:00

5.5 KiB

WP2: packages/macp — MACP Protocol Package

Context

Port the MACP protocol layer from Python (in ~/src/mosaic-stack/tools/macp/) to TypeScript as packages/macp in this monorepo. This package provides the foundational protocol types, quality gate execution, credential resolution, and event system that packages/coord and plugins/macp depend on.

Board decisions that constrain this work:

  • No Python in the new repo — everything rewrites to TypeScript
  • OpenBrain learning capture/recall is OUT OF SCOPE (deferred to future brief)
  • 85% test coverage on TS implementation files
  • Credential resolver behavior must be captured as test fixtures BEFORE rewrite
  • Clean index.ts exports, no internal path leakage

Source Files (Python → TypeScript)

1. credential-resolver.ts

Source: ~/src/mosaic-stack/tools/macp/dispatcher/credential_resolver.py

Resolution order (MUST preserve exactly):

  1. Mosaic credential files (~/.config/mosaic/credentials/{provider}.env)
  2. OpenClaw config (~/.openclaw/openclaw.json) — env block + models.providers.{provider}.apiKey
  3. Ambient environment variables
  4. CredentialError (failure)

Key behaviors to preserve:

  • Provider registry: anthropic, openai, zai → env var names + credential file paths + OC config paths
  • Dotenv parser: handles single/double quotes, comments, blank lines
  • JSON5 stripping: placeholder-extraction approach (NOT naive regex) — protects URLs and timestamps inside string values
  • OC config permission check: warn on world-readable, skip if wrong owner
  • Redacted marker detection: __OPENCLAW_REDACTED__ values skipped
  • Task-level override via credentials.provider_key_env

2. gate-runner.ts

Source: ~/src/mosaic-stack/tools/macp/controller/gate_runner.py

Three gate types:

  • mechanical: shell command, pass = exit code 0
  • ai-review: shell command producing JSON, parse findings, fail on blockers
  • ci-pipeline: placeholder (always passes for now)

Key behaviors:

  • normalize_gate(): accepts string or dict, normalizes to gate entry
  • run_gate(): executes single gate, returns result with pass/fail
  • run_gates(): executes all gates, emits events, returns (all_passed, results)
  • AI review parsing: _count_ai_findings() reads stats.blockers or findings[].severity
  • fail_on modes: "blocker" (default) or "any"

3. event-emitter.ts

Source: ~/src/mosaic-stack/tools/macp/controller/gate_runner.py (emit_event, append_event functions) + ~/src/mosaic-stack/tools/macp/events/

  • Append structured events to ndjson file
  • Event types: task.assigned, task.started, task.completed, task.failed, task.escalated, task.gated, task.retry.scheduled, rail.check.started, rail.check.passed, rail.check.failed
  • Each event: event_id (uuid), event_type, task_id, status, timestamp, source, message, metadata

4. types.ts

Source: ~/src/mosaic-stack/tools/macp/protocol/task.schema.json

TypeScript types for:

  • Task (id, title, status, dispatch, runtime, depends_on, depends_on_policy, quality_gates, timeout_seconds, metadata, etc.)
  • Event (event_id, event_type, task_id, status, timestamp, source, message, metadata)
  • GateResult (command, exit_code, type, passed, output, findings, blockers)
  • TaskResult (task_id, status, completed_at, exit_code, gate_results, files_changed, etc.)
  • CredentialError, ProviderRegistry

5. schemas/ (copy)

Copy ~/src/mosaic-stack/tools/macp/protocol/task.schema.json as-is.

Package Structure

packages/macp/
├── src/
│   ├── index.ts
│   ├── types.ts
│   ├── credential-resolver.ts
│   ├── gate-runner.ts
│   ├── event-emitter.ts
│   └── schemas/
│       └── task.schema.json
├── __tests__/
│   ├── credential-resolver.test.ts
│   ├── gate-runner.test.ts
│   └── event-emitter.test.ts
├── package.json
├── tsconfig.json
└── vitest.config.ts

Package.json

{
  "name": "@mosaic/macp",
  "version": "0.0.1",
  "type": "module",
  "exports": {
    ".": "./src/index.ts"
  },
  "dependencies": {},
  "devDependencies": {
    "vitest": "workspace:*",
    "typescript": "workspace:*"
  }
}

Zero external dependencies. Uses node:fs, node:path, node:child_process, node:crypto only.

Test Requirements

Port ALL existing Python tests as TypeScript equivalents:

  • test_resolve_from_file → credential file resolution
  • test_resolve_from_ambient → ambient env resolution
  • test_resolve_from_oc_config_env_block → OC config env block
  • test_resolve_from_oc_config_provider_apikey → OC config provider
  • test_oc_config_precedence → mosaic file wins over OC config
  • test_oc_config_missing_file → graceful fallback
  • test_json5_strip → structural transforms
  • test_json5_strip_urls_and_timestamps → URLs/timestamps survive
  • test_redacted_values_skipped → redacted marker detection
  • test_oc_config_permission_warning → file permission check
  • test_resolve_missing_raises → CredentialError thrown
  • Gate runner: mechanical pass/fail, AI review parsing, ci-pipeline placeholder
  • Event emitter: append to ndjson, event structure validation

ESM Requirements

  • "type": "module" in package.json
  • NodeNext module resolution in tsconfig
  • .js extensions in all imports
  • No CommonJS (require, module.exports)

Integration Points

After this package is built:

  • packages/coord should import @mosaic/macp for event emission and gate types
  • plugins/macp should import @mosaic/macp for credential resolution and protocol types