generated from coulomb/repo-seed
Complete extension SDK maturity
This commit is contained in:
@@ -65,6 +65,8 @@ when a wrapper script or container entrypoint should keep commands shorter.
|
||||
For the repeatable external extension acceptance path, including validation,
|
||||
planning, live execution, and retained result review, see
|
||||
`docs/EXTERNAL-EXTENSION-ACCEPTANCE.md`.
|
||||
For extension-author contracts such as profile schema descriptors and
|
||||
normalizer plug-ins, see `docs/EXTENSION-SDK.md`.
|
||||
|
||||
## CLI Results
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ The key runtime fields are:
|
||||
- `check_groups`: named groups that assessment profiles can select.
|
||||
- `preflight_runner`: optional runner ID used before selected check groups.
|
||||
- `runner_entrypoints`: concrete runner declarations.
|
||||
- `normalizers`: optional plug-ins that convert native runner output into the
|
||||
stable runner-result shape before evidence is written.
|
||||
- `mappings`: mapping set IDs under `mappings/<mapping-id>.json`.
|
||||
- `certification_boundary`: explicit statement of what the extension does not
|
||||
certify.
|
||||
@@ -283,6 +285,71 @@ or `infrastructure_error`, downstream check groups for that extension are not
|
||||
executed; they receive `blocked` evidence with `blocked_reason:
|
||||
preflight_failed`.
|
||||
|
||||
## Normalizer Plug-ins
|
||||
|
||||
Runners can keep returning guide-board-ready result objects directly. When a
|
||||
runner wraps a native harness or scanner that writes its own result format, the
|
||||
extension can add a normalizer descriptor:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "native-probe-normalizer",
|
||||
"kind": "python_module",
|
||||
"module_path": "normalizers/native_probe.py",
|
||||
"callable": "normalize",
|
||||
"runner_ref": "native-probe",
|
||||
"description": "Converts native runner output into guide-board evidence."
|
||||
}
|
||||
```
|
||||
|
||||
Normalizers are declared in `extension.json` under `normalizers`. The original
|
||||
string shorthand remains valid for descriptive-only entries, but only descriptor
|
||||
objects are loaded and invoked by the core.
|
||||
|
||||
The first supported normalizer kind is `python_module`. Its module path is
|
||||
resolved relative to the extension root and must stay inside that root. The
|
||||
callable receives one context object:
|
||||
|
||||
- `root`: guide-board core root path as a string.
|
||||
- `extension_path`: extension 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 normalized.
|
||||
- `target_profile`: target profile snapshot.
|
||||
- `assessment_profile`: assessment profile snapshot.
|
||||
- `normalizer`: manifest normalizer descriptor.
|
||||
- `runner_result`: the current runner-result object.
|
||||
|
||||
A normalizer returns any subset of the runner-result fields:
|
||||
|
||||
```python
|
||||
def normalize(context: dict) -> dict:
|
||||
return {
|
||||
"result": "pass",
|
||||
"observations": ["Native result was normalized."],
|
||||
"facts": {"native_status": "ok"},
|
||||
"artifact_refs": ["artifacts/native-result.json"],
|
||||
"requirement_refs": ["framework.requirement"],
|
||||
}
|
||||
```
|
||||
|
||||
The core merges the normalizer output over the runner result:
|
||||
|
||||
- `result` replaces the previous result.
|
||||
- `observations` are appended.
|
||||
- `facts` are merged.
|
||||
- `artifact_refs` and `requirement_refs` are deduplicated.
|
||||
- `normalizer_refs` is recorded in evidence facts when any normalizer runs.
|
||||
|
||||
If a normalizer raises an exception, the step becomes
|
||||
`infrastructure_error` evidence and the run still produces its normal artifact
|
||||
set.
|
||||
|
||||
The bundled `extensions/sdk-fixture` extension is the copyable reference path
|
||||
for profile schemas, a native-output runner, a normalizer, mappings, and fixture
|
||||
profiles.
|
||||
|
||||
## Result Statuses
|
||||
|
||||
Initial statuses:
|
||||
@@ -303,11 +370,14 @@ Initial statuses:
|
||||
## Current Extension Examples
|
||||
|
||||
- `sample-noop`: no runner, used to validate the core contracts.
|
||||
- `sdk-fixture`: compact SDK fixture covering profile schemas, runner output,
|
||||
normalizer invocation, mapping, and fixture profiles.
|
||||
- `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.
|
||||
- Broaden normalizer examples as real external extensions adopt native harness
|
||||
result formats.
|
||||
- Add more extension-owned schema validation examples for assessment-specific
|
||||
domain constraints.
|
||||
|
||||
@@ -15,6 +15,9 @@ domain-specific harness logic into the core.
|
||||
runtime dependencies, and harness behavior remain owned by that extension
|
||||
repository.
|
||||
|
||||
For a dependency-light SDK reference extension that can be copied into a
|
||||
temporary external repository, see `extensions/sdk-fixture`.
|
||||
|
||||
## Acceptance Stages
|
||||
|
||||
Run these stages from the guide-board repository.
|
||||
|
||||
@@ -93,7 +93,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"normalizers": { "type": "array", "items": { "type": "string" } },
|
||||
"normalizers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": ["string", "object"],
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "kind", "module_path", "callable"],
|
||||
"properties": {
|
||||
"id": { "type": "string" },
|
||||
"kind": { "type": "string", "enum": ["python_module"] },
|
||||
"module_path": { "type": "string" },
|
||||
"callable": { "type": "string" },
|
||||
"runner_ref": { "type": ["string", "null"] },
|
||||
"description": { "type": ["string", "null"] }
|
||||
}
|
||||
}
|
||||
},
|
||||
"mappings": { "type": "array", "items": { "type": "string" } },
|
||||
"report_fragments": { "type": "array", "items": { "type": "string" } },
|
||||
"dependencies": { "type": "array", "items": { "type": "string" } },
|
||||
|
||||
Reference in New Issue
Block a user