# Guide Board Extension SDK Status: draft Created: 2026-05-07 ## Purpose This document defines the first extension integration contract for `guide-board`. It is intentionally small: extensions declare metadata in `extension.json`, the core discovers them, and runners can produce normalized evidence through a stable dictionary contract. ## Extension Layout Incubating extensions live under: ```text extensions// INTENT.md extension.json src/ docs/ schemas/ checks/ mappings/ profiles/ runners/ normalizers/ reports/ workplans/ ``` Only `INTENT.md` and `extension.json` are required for discovery. Additional folders appear as the extension grows. ## Manifest Contract `extension.json` must validate against: ```text docs/schemas/extension-manifest.schema.json ``` The key runtime fields are: - `id`: must match the extension directory name. - `extension_type`: one of the supported archetypes from the architecture blueprint. - `supported_frameworks`: framework IDs this extension can contribute evidence for. - `check_groups`: named groups that assessment profiles can select. - `preflight_runner`: optional runner ID used before selected check groups. - `runner_entrypoints`: concrete runner declarations. - `certification_boundary`: explicit statement of what the extension does not certify. ## Runner Entry Points Runner entry points currently support these kinds: - `python_module`: load a Python file from the extension directory and call a function. - `command`: execute a manifest-declared argv without shell expansion. The core writes a context JSON file and expects the command to print a JSON runner result to stdout. - `external`: declare an external harness that the baseline core cannot execute yet. Example: ```json { "id": "cmis-browser-preflight", "kind": "python_module", "module_path": "src/open_cmis_tck/preflight.py", "callable": "run", "command": null, "description": "Checks whether the CMIS Browser Binding endpoint is reachable." } ``` Command runner example: ```json { "id": "opencmis-tck", "kind": "command", "module_path": null, "callable": null, "command": ["python3", "runners/opencmis_tck.py", "--context", "{context_json}"], "description": "Checks dependency posture and prepares OpenCMIS TCK execution." } ``` Command placeholders: - `{context_json}`: generated context file for the current step. - `{root}`: repository root. - `{run_dir}`: current run directory. - `{extension_path}`: current extension directory. The command is executed with the extension directory as its working directory. The core does not use a shell for command runners. ## Python Runner Contract A Python runner receives one context object and returns one result object. ```python def run(context: dict) -> dict: return { "result": "pass", "observations": ["Observed the expected condition."], "facts": {"key": "value"}, "artifact_refs": [], } ``` Context fields: - `root`: repository root path as a string. - `run_dir`: output run directory path as a string. - `run_id`: current run ID. - `plan`: full run plan snapshot. - `step`: the step being executed. - `target_profile`: target profile snapshot. - `assessment_profile`: assessment profile snapshot. - `extension_path`: extension directory path as a string. - `runner`: manifest runner declaration. Result fields: - `result`: one of the guide-board evidence result statuses. - `observations`: human-readable observations. - `facts`: structured facts extracted by the runner. - `artifact_refs`: references to raw artifacts written by the runner. If a Python runner raises an exception, the core converts that failure into `infrastructure_error` evidence so the assessment package remains complete. ## Result Statuses Initial statuses: - `pass` - `fail` - `warning` - `manual` - `not_applicable` - `skipped` - `expected_gap` - `waiver_applied` - `unsupported_by_design` - `infrastructure_error` - `blocked` - `unknown` ## Current Extension Examples - `sample-noop`: no runner, used to validate the core contracts. - `open-cmis-tck`: provides a Python CMIS Browser Binding preflight runner and declares the future external OpenCMIS TCK runner. ## Next SDK Steps - Add artifact helper APIs for extension-generated raw files. - Add normalizer and mapping plug-in contracts. - Add extension-owned schema validation for domain-specific target profile fields.