# 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 Bundled incubating extensions live under: ```text extensions// INTENT.md extension.json src/ docs/ schemas/ evidence-requests/ checks/ mappings/ profiles/ runners/ normalizers/ reports/ workplans/ ``` Production extensions may also live in their own repositories. The repository root is then the extension root and must contain `extension.json`: ```text open-cmis-tck/ INTENT.md extension.json src/ mappings/ profiles/ runners/ workplans/ ``` Pass external extension repos to the core CLI with: ```sh guide-board --extension-dir ../open-cmis-tck extensions list ``` Multiple `--extension-dir` values are allowed. `GUIDE_BOARD_EXTENSION_PATHS` may also provide an OS-path-separated list for local automation and containers. 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. - `mappings`: mapping set IDs under `mappings/.json`. - `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. Runner context values are stable for bundled and external extensions: - `root`: the guide-board core root. - `extension_path`: the absolute path to the extension root. - `run_dir`: the current run output directory. - `plan`: the immutable run plan snapshot. ## Mapping Sets Mapping sets connect normalized evidence requirement refs to capability groups, controls, conformance classes, quality dimensions, or other assessment targets. Each mapping set lives under: ```text extensions//mappings/.json ``` and validates against: ```text docs/schemas/mapping-set.schema.json ``` The core does not embed domain policy. It only joins evidence `requirement_refs` to extension-owned mappings and writes normalized mapping records to: ```text runs//normalized/mappings.json ``` ## Evidence Request Sets Procedural and hybrid compliance extensions may include evidence request sets under: ```text evidence-requests/.json ``` These files validate against: ```text docs/schemas/evidence-request-set.schema.json ``` Evidence request sets are for collection guidance and review workflow. They should reference official requirements by stable IDs or user-held licensed material, but they must not redistribute proprietary standard text. A starter template lives at: ```text extensions/_template/evidence-request-set.json ``` See `docs/COMPLIANCE-EVIDENCE-PACKS.md` for the compliance-pack strategy. ## Expectations And Waivers Assessment profiles may reference expectation and waiver sets: ```json { "expectations_ref": "profiles/expectations/example.json", "waivers_ref": "profiles/waivers/example.json" } ``` Expectation sets mark known posture as expected. Waiver sets mark approved, time-bounded exceptions. Both are applied after findings are generated, and the assessment package records policy summary counts. ## 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. Artifact refs must be paths relative to the run directory. After runner execution, the core fingerprints existing artifact refs into the assessment package `artifact_manifest`. If a Python runner raises an exception, the core converts that failure into `infrastructure_error` evidence so the assessment package remains complete. Preflight runners are gates. If an extension preflight returns `fail`, `blocked`, or `infrastructure_error`, downstream check groups for that extension are not executed; they receive `blocked` evidence with `blocked_reason: preflight_failed`. ## 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 normalizer plug-in contracts. - Add extension-owned schema validation for domain-specific target profile fields.