# Schema — .reversa/context/surface.json

File generated by the Scout. Used by the other agents as a source of structured context.

## Complete structure

```json
{
  "generated_at": "2026-04-26T10:00:00Z",
  "project_root": "/path/to/project",
  "languages": [
    { "name": "TypeScript", "extensions": [".ts", ".tsx"], "file_count": 142 },
    { "name": "JavaScript", "extensions": [".js", ".mjs"], "file_count": 23 }
  ],
  "primary_language": "TypeScript",
  "frameworks": [
    { "name": "Next.js", "version": "14.2.0", "source": "package.json" },
    { "name": "Prisma", "version": "5.10.0", "source": "package.json" }
  ],
  "package_manager": "npm",
  "entry_points": [
    { "path": "src/app/layout.tsx", "type": "app_entry" },
    { "path": "src/server.ts", "type": "server_entry" }
  ],
  "signals": [
    {
      "type": "cs_agent_profile_detected",
      "profile": "CS253",
      "ot_home": "E:\\CS253",
      "executable_path": "F:\\smoke\\CS253\\cs-agent.exe",
      "help_sha256": "<64-hex>",
      "evidence": ["content-server detect", "CS253", "E:\\CS253"]
    }
  ],
  "config_files": [
    "next.config.js", ".env.example", "tsconfig.json"
  ],
  "ci_cd": [
    ".github/workflows/deploy.yml"
  ],
  "docker": {
    "dockerfile": "Dockerfile",
    "compose": "docker-compose.yml"
  },
  "database_hints": [
    { "path": "prisma/schema.prisma", "type": "prisma_schema" },
    { "path": "prisma/migrations/", "type": "migrations_dir" }
  ],
  "test_framework": "Jest",
  "test_file_count": 47,
  "modules": [
    "auth", "orders", "payments", "users", "notifications"
  ],
  "content_server": {
    "profile": "CS253",
    "schema_version": 3,
    "source_file_count": 1200,
    "support_asset_count": 140,
    "counts_by_module": {
      "core": 800,
      "web": 400
    },
    "confidence_counts": {
      "confirmed": 2000,
      "inferred": 120,
      "gap": 8
    },
    "unresolved_refs_by_kind": {
      "function": 3
    }
  },
  "total_files": 312,
  "organization_suggestion": {
    "granularity": "module",
    "rationale": "The top-level folder structure is organized by domain: auth/, orders/, payments/, users/, notifications/.",
    "signals": [
      { "type": "top_level_domain_folders", "evidence": ["src/auth/", "src/orders/", "src/payments/"] }
    ],
    "features": []
  }
}
```

## Required fields

`generated_at`, `languages`, `primary_language`, `frameworks`, `entry_points`, `modules`, `organization_suggestion`

## Optional fields

All others; include only what is found.

### Field `signals`

Optional top-level detection signals. Scout uses this for cheap pre-walk facts that other agents or the Reversa orchestrator can react to. Content Server signal types are:

- `cs_agent_probe_failed`
- `cs_agent_no_profile`
- `cs_agent_profile_detected`
- `cs_agent_profile`
- `cs_agent_snapshot_failed`

When the signal comes from a successful detect or snapshot, include the current fingerprint fields when available:

- `profile`
- `ot_home`
- `executable_path`
- `help_sha256`

The Reversa orchestrator uses these fields to suppress repeated migration prompts only for the same detected profile/executable fingerprint.

### Field `content_server`

Optional. Present only when `[integrations.cs_agent].enabled = true` and `.reversa/context/cs-agent/_meta.json` exists. Values are copied from the read-only cs-agent snapshot. The Scout must not populate this field by recursively walking `profile-info.json.profile.paths.srcdir`.

When this field is present, Scout may skip recursive traversal only for the exact absolute source directory reported by `profile-info.json.profile.paths.srcdir` or, for older snapshots, the top-level `srcdir` field. It must keep the normal walk for every path outside that exact directory.

## Field `organization_suggestion`

Suggestion for how to organize the specs for this project. Read by the Reversa orchestrator to pre-select the default option in the spec organization menu.

### Sub-fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `granularity` | string | yes | One of: `module`, `use-case`, `endpoint`, `hybrid`, `feature`, `custom`. The Scout never suggests `custom` — that value comes from the user's choice only. |
| `rationale` | string | yes | Short sentence explaining why this granularity was chosen. Appears in the menu as the Scout's "Reason:". |
| `signals` | array | yes | List of detected signals that led to the suggestion. Each item has `type` and `evidence` (list of paths). May be empty when the `feature` fallback is used. |
| `features` | array | required when `granularity = "feature"` | List of feature names discovered by the Scout. Each name becomes a top-level folder. |

### Heuristics for defining `granularity`

| Detected signal | Suggested `granularity` |
|-----------------|-------------------------|
| Centralized routing (`routes.*`, `urls.py`, `*Controller.cs`, `@RestController`) | `endpoint` |
| Top-level folders with domain names (`auth/`, `orders/`, `payments/`) | `module` |
| Gherkin / behavior-driven E2E specs (`features/*.feature`, `*.spec.*` BDD) | `use-case` |
| Multiple signals coexisting with similar weight | `hybrid` |
| No clear organizational signal | `feature` (fallback; populate `features` with what could be extracted) |

### Immutability

After the first run, the orchestrator persists the suggested `granularity` in `.reversa/config.toml` under the `scout_suggestion` field. On re-runs, the Scout may regenerate `surface.json` (the legacy project may have changed), but the orchestrator does NOT update `scout_suggestion` in `config.toml` (RF-14 of the spec organization specification).

## Note

Use this schema as a guide. If a field does not apply to the project, omit it, except for the required fields listed above.
