Overview
Agents, workers, CI jobs, and Mac clients POST a Project Report JSON document to POST /api/v1/project-reports. ProjectMind validates it against a published JSON Schema, stores the raw payload, normalizes queryable rows, and updates a per-environment latest pointer. Historical reports are never deleted.
The versioned HTTPS API is the canonical ingestion interface. Future MCP tools are read-only facades over the same application services — do not treat MCP as the write path.
Project manifest (imemory.project.yaml)
Connected repositories declare capabilities, commands, protected paths, verification, and autonomy templates in imemory.project.yaml. ProjectMind validates the manifest, caches the last valid snapshot, and drives the improvement loop from configuration — not from project-name branches.
- Schema: manifest-schema.json
- Example: examples/imemory.project.yaml (sample-project fixture)
- Autonomy templates:
observe-only,propose-only,manual-execution,safe-pull-request,low-risk-autonomous,finance-safe,privacy-sensitive - Category policies (backend-enforced): product may code; relationship/financial categories route to task hub / briefing / user-action queues and never the coding agent.
Connect a new project (no ProjectMind code change)
- Create the project in ProjectMind and connect its Git repository (configure a runtime project path).
- Add
imemory.project.yamlandAGENTS.mdto the repository. - Refresh/load the manifest from project settings or the local Mac agent path.
- Mint a project-report credential and POST the first report.
- Select an autonomy template (or declare it in the manifest).
- Confirm readiness: manifest valid, reporting configured, required commands present, coding/verification capabilities as needed.
Rule: new project = configuration and contract implementation. New platform capability = ProjectMind code change.
Quick start
- Create a project report credential (token prefix
impr_) with scopeproject-reports:writefor your project. From the ProjectMind repo:npm run mint:project-report-credential -- --project-id <uuid> --name "reporter". - Download the minimal example and set
project.idto your ProjectMind project UUID. - POST to
/api/v1/project-reportswith the bearer token.
curl -X POST https://your-imemory-host/api/v1/project-reports \
-H "Authorization: Bearer impr_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d @minimal.jsonAuthentication
Use a per-project credential. Pass the token as Authorization: Bearer impr_… or x-api-key. Tokens are stored as SHA-256 hashes only. Required write scope: project-reports:write. Credentials may expire or be revoked; expired/revoked tokens are rejected.
The credential is bound to a single project. Submitting a report whose project.id does not match returns 403.
Complete schema reference
Generated from the canonical JSON Schema (no hand-maintained field list). Unknown root-level properties are rejected; unknown keys inside extensions are accepted.
| Path | Type | Req | Description |
|---|---|---|---|
| schemaVersion | const "1.0" | yes | Report schema version. Currently only "1.0" is accepted. |
| reportId | string | yes | Client-generated idempotency key for this report. Prefer UUIDv4. |
| generatedAt | string (date-time) | yes | ISO-8601 timestamp when the report was generated. |
| project | object | yes | |
| project.id | string | yes | ProjectMind project UUID (or stable external id mapped to a project). |
| project.name | string | yes | |
| project.environment | enum: "production" | "staging" | "development" | "test" | "preview" | yes | |
| project.status | enum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance" | yes | |
| project.slug | string | ||
| project.description | string | ||
| project.version | string | Application or release version string. | |
| project.url | string | Primary public URL for the project. | |
| summary | object | ||
| summary.headline | string | ||
| summary.body | string | ||
| summary.highlights | array<string> | ||
| health | object | ||
| health.score | number | Optional self-reported health score (0–100). ProjectMind does not compute this. | |
| health.status | enum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance" | ||
| health.checkedAt | string (date-time) | ||
| health.components | array<object> | ||
| health.components[].name | string | yes | |
| health.components[].status | enum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance" | yes | |
| health.components[].message | string | ||
| metrics | array<object> | ||
| metrics[].key | string | yes | |
| metrics[].value | number | yes | |
| metrics[].unit | string | ||
| metrics[].timestamp | string (date-time) | ||
| metrics[].labels | object | ||
| deployments | array<object> | ||
| deployments[].id | string | yes | |
| deployments[].status | enum: "pending" | "building" | "deploying" | "success" | "failed" | "rolled_back" | "cancelled" | yes | |
| deployments[].timestamp | string (date-time) | yes | |
| deployments[].environment | enum: "production" | "staging" | "development" | "test" | "preview" | ||
| deployments[].version | string | ||
| deployments[].url | string | ||
| deployments[].commitSha | string | ||
| deployments[].message | string | ||
| issues | array<object> | ||
| issues[].id | string | yes | |
| issues[].title | string | yes | |
| issues[].severity | enum: "critical" | "high" | "medium" | "low" | "info" | yes | |
| issues[].status | enum: "open" | "acknowledged" | "resolved" | "ignored" | ||
| issues[].description | string | ||
| issues[].detectedAt | string (date-time) | ||
| issues[].resolvedAt | string,null (date-time) | ||
| issues[].source | string | ||
| issues[].url | string | ||
| issues[].category | enum: "product" | "platform_reliability" | "test_coverage" | "documentation" | "relationship_action" | "financial_insight" | "financial_action" | "operational_action" | "user_action" | "security_action" | "policy_change" | "credential_change" | "audit_change" | "destructive_data_change" | "production_deployment" | "external_communication" | "data_review" | product → coding loop; relationship_action / financial_insight / financial_action → non-coding workflows only. | |
| issues[].kind | enum: "follow_up" | "upcoming_event" | "overdue_commitment" | "data_review" | "other" | "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit" | Optional subtype for relationship_action, financial_insight, or financial_action issues. | |
| issues[].priority | enum: "low" | "medium" | "high" | "urgent" | ||
| issues[].dueAt | string (date-time) | ||
| issues[].personRef | string | Opaque internal person reference. Never a production person record payload. | |
| issues[].suggestedTaskTitle | string | ||
| issues[].explanation | string | ||
| issues[].insightType | enum: "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "other" | ||
| issues[].factKind | enum: "observed_fact" | "inference" | "recommendation" | "incomplete_data" | ||
| issues[].coveragePeriodStart | string (date-time) | ||
| issues[].coveragePeriodEnd | string (date-time) | ||
| issues[].confidence | number | ||
| issues[].supportingDataRef | string | ||
| issues[].briefingEligible | boolean | ||
| issues[].voiceEligible | boolean | ||
| issues[].actionType | enum: "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit" | "data_review" | "other" | ||
| issues[].supportingInsightRef | string | ||
| issues[].dataCoverageStatement | string | ||
| issues[].estimatedEffect | string | ||
| issues[].risk | enum: "low" | "medium" | "high" | "critical" | ||
| issues[].requiresConfirmation | boolean | ||
| issues[].deepLink | string | ||
| relationshipActions | array<object> | My People relationship-action candidates. Never enter the coding-agent lifecycle. | |
| relationshipActions[].id | string | yes | |
| relationshipActions[].title | string | yes | |
| relationshipActions[].description | string | ||
| relationshipActions[].suggestedTaskTitle | string | ||
| relationshipActions[].priority | enum: "low" | "medium" | "high" | "urgent" | ||
| relationshipActions[].dueAt | string (date-time) | ||
| relationshipActions[].personRef | string | Opaque internal person reference only. | |
| relationshipActions[].evidenceRef | string | ||
| relationshipActions[].kind | enum: "follow_up" | "upcoming_event" | "overdue_commitment" | "data_review" | "other" | ||
| relationshipActions[].source | string | ||
| financialInsights | array<object> | MoneySprout financial-insight summaries. Aggregated only — never enter the coding-agent lifecycle. | |
| financialInsights[].id | string | yes | |
| financialInsights[].title | string | yes | |
| financialInsights[].explanation | string | ||
| financialInsights[].insightType | enum: "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "other" | ||
| financialInsights[].factKind | enum: "observed_fact" | "inference" | "recommendation" | "incomplete_data" | ||
| financialInsights[].coveragePeriodStart | string (date-time) | ||
| financialInsights[].coveragePeriodEnd | string (date-time) | ||
| financialInsights[].confidence | number | ||
| financialInsights[].supportingDataRef | string | ||
| financialInsights[].briefingEligible | boolean | ||
| financialInsights[].voiceEligible | boolean | ||
| financialInsights[].deepLink | string | ||
| financialInsights[].source | string | ||
| financialActions | array<object> | MoneySprout financial-action suggestions. Never execute money movement; never enter the coding-agent lifecycle. | |
| financialActions[].id | string | yes | |
| financialActions[].title | string | yes | |
| financialActions[].explanation | string | ||
| financialActions[].actionType | enum: "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit" | "data_review" | "other" | ||
| financialActions[].supportingInsightRef | string | ||
| financialActions[].dataCoverageStatement | string | ||
| financialActions[].estimatedEffect | string | ||
| financialActions[].risk | enum: "low" | "medium" | "high" | "critical" | ||
| financialActions[].requiresConfirmation | boolean | ||
| financialActions[].deepLink | string | ||
| financialActions[].source | string | ||
| capabilities | array<string> | Self-reported project capabilities (e.g. contact-sync, reminders). | |
| tasks | array<object> | ||
| tasks[].id | string | yes | |
| tasks[].title | string | yes | |
| tasks[].status | enum: "todo" | "in_progress" | "blocked" | "done" | "cancelled" | yes | |
| tasks[].priority | enum: "low" | "medium" | "high" | "urgent" | ||
| tasks[].assignee | string | ||
| tasks[].dueAt | string (date-time) | ||
| tasks[].url | string | ||
| agent | object | ||
| agent.id | string | ||
| agent.name | string | ||
| agent.kind | enum: "mac-agent" | "coding-agent" | "background-worker" | "mobile-app" | "saas" | "ci" | "other" | ||
| agent.version | string | ||
| agent.platform | string | ||
| agent.hostname | string | ||
| links | object | ||
| links.dashboard | string | ||
| links.repository | string | ||
| links.docs | string | ||
| links.logs | string | ||
| links.extra | object | ||
| extensions | object | Vendor-specific or experimental fields. Unknown keys inside extensions are accepted. |
Examples
Valid examples live under spec/examples/ and are validated in CI: minimal, full, SaaS, mobile app, background worker, Mac agent, and coding agent.
API reference
Generated from the OpenAPI document.
| Method | Path | Auth | Summary |
|---|---|---|---|
| POST | /api/v1/project-reports | Project report credential | Ingest a project report |
| GET | /api/v1/projects | Project report credential | List projects visible to the credential |
| GET | /api/v1/projects/{projectId} | Project report credential | Get a project summary with latest report pointer |
| GET | /api/v1/projects/{projectId}/reports/latest | Project report credential | Get the latest report for a project |
| GET | /api/v1/projects/{projectId}/reports | Project report credential | List historical reports for a project |
| GET | /api/v1/project-report-schema | None | Download the Project Report JSON Schema |
| GET | /openapi.json | None | OpenAPI document (JSON) |
| GET | /openapi.yaml | None | OpenAPI document (YAML) |
Rate limit: 60 requests / minute per credential. Success shape for ingest: { accepted, reportId, projectId, schemaVersion, receivedAt }.
Validation rules
- Body must match JSON Schema draft 2020-12;
additionalProperties: falseat the root (and nested objects exceptextensions). - Only
schemaVersion: "1.0"is accepted. - Enums enforced for status, environment, severity, task status, deployment status.
- Timestamps must be ISO-8601 date-time.
- Maximum body size: 512 KiB.
Retry & idempotency
Clients should set a stable reportId (and optionally Idempotency-Key). Replaying the same id with the same payload returns 202 with duplicate: true. A different payload for the same id returns 409. Retry with exponential backoff on 429 / 5xx — do not retry 401, 403, or 422.
TypeScript / Python / cURL
import { IMemoryProjectReporter } from "@imemory/project-reporter";
const reporter = new IMemoryProjectReporter({
baseUrl: "https://your-imemory-host",
token: process.env.IMEMORY_PROJECT_REPORT_TOKEN!,
});
await reporter.submit({
project: {
id: "11111111-1111-1111-1111-111111111111",
name: "Example App",
environment: "production",
status: "healthy",
},
});import json, urllib.request, uuid, datetime
token = "impr_YOUR_TOKEN"
body = {
"schemaVersion": "1.0",
"reportId": str(uuid.uuid4()),
"generatedAt": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z"),
"project": {
"id": "11111111-1111-1111-1111-111111111111",
"name": "Example App",
"environment": "production",
"status": "healthy",
},
}
req = urllib.request.Request(
"https://your-imemory-host/api/v1/project-reports",
data=json.dumps(body).encode(),
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Idempotency-Key": body["reportId"],
},
method="POST",
)
print(urllib.request.urlopen(req).read().decode())curl -X POST https://your-imemory-host/api/v1/project-reports \
-H "Authorization: Bearer impr_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d @minimal.jsonMCP architecture
MCP is not the primary write interface for project reports. Planned read-only MCP tools (list_projects, get_project, get_latest_project_report, get_project_metrics, get_project_issues, get_project_timeline, compare_projects, generate_project_briefing, find_projects_requiring_attention) call the same internal services as this REST API. Write tools will not be added for report ingestion.
Facades live in src/lib/project-reports/mcp-facade.server.ts.
Changelog
- 1.0.0 — Initial Project Reports API, schema, OpenAPI, docs, and SDK scaffold.