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.
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):
- Mosaic credential files (
~/.config/mosaic/credentials/{provider}.env) - OpenClaw config (
~/.openclaw/openclaw.json) — env block + models.providers.{provider}.apiKey - Ambient environment variables
- 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 0ai-review: shell command producing JSON, parse findings, fail on blockersci-pipeline: placeholder (always passes for now)
Key behaviors:
normalize_gate(): accepts string or dict, normalizes to gate entryrun_gate(): executes single gate, returns result with pass/failrun_gates(): executes all gates, emits events, returns (all_passed, results)- AI review parsing:
_count_ai_findings()reads stats.blockers or findings[].severity fail_onmodes: "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 resolutiontest_resolve_from_ambient→ ambient env resolutiontest_resolve_from_oc_config_env_block→ OC config env blocktest_resolve_from_oc_config_provider_apikey→ OC config providertest_oc_config_precedence→ mosaic file wins over OC configtest_oc_config_missing_file→ graceful fallbacktest_json5_strip→ structural transformstest_json5_strip_urls_and_timestamps→ URLs/timestamps survivetest_redacted_values_skipped→ redacted marker detectiontest_oc_config_permission_warning→ file permission checktest_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
.jsextensions in all imports- No CommonJS (
require,module.exports)
Integration Points
After this package is built:
packages/coordshould import@mosaic/macpfor event emission and gate typesplugins/macpshould import@mosaic/macpfor credential resolution and protocol types