plugin-scanner 3.2.0__py3-none-any.whl → 3.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codex_plugin_scanner/guard/extension_builder/kit.py +43 -6
- codex_plugin_scanner/guard/extension_builder/listing.py +44 -6
- codex_plugin_scanner/guard/extension_builder/listing.v2.schema.json +126 -0
- codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-3.2.0.dist-info → plugin_scanner-3.3.0.dist-info}/METADATA +52 -16
- {plugin_scanner-3.2.0.dist-info → plugin_scanner-3.3.0.dist-info}/RECORD +9 -8
- {plugin_scanner-3.2.0.dist-info → plugin_scanner-3.3.0.dist-info}/WHEEL +0 -0
- {plugin_scanner-3.2.0.dist-info → plugin_scanner-3.3.0.dist-info}/entry_points.txt +0 -0
- {plugin_scanner-3.2.0.dist-info → plugin_scanner-3.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -99,6 +99,29 @@ def _report(discovery: Discovery, review: Review) -> dict[str, object]:
|
|
|
99
99
|
def _readme(discovery: Discovery) -> str:
|
|
100
100
|
metadata = discovery.metadata
|
|
101
101
|
safe_name = re.sub(r"([\\`*_{}\[\]()#+.!|<>~-])", r"\\\1", metadata.name)
|
|
102
|
+
if metadata.kind == "cli":
|
|
103
|
+
verification = f"""The command source is `{command_source_path(metadata)}` and its portable fixture
|
|
104
|
+
is `{command_fixture_path(metadata)}`. Kit validation compiles the source and
|
|
105
|
+
runs these cases with Rust. CLI kits do not generate a Python detector or a
|
|
106
|
+
Python test module.
|
|
107
|
+
|
|
108
|
+
After integration, follow the [native validation sequence](https://github.com/hashgraph-online/hol-guard/blob/main/docs/guard/extension-builder/VALIDATION.md):
|
|
109
|
+
regenerate the complete program, rebuild the native compiler and runtime, and
|
|
110
|
+
run the fixture with a build envelope assembled from the destination checkout's
|
|
111
|
+
canonical sources. The kit's `base: "packaged"` envelope is for a new addition;
|
|
112
|
+
it cannot replace an extension already embedded in the rebuilt compiler.
|
|
113
|
+
"""
|
|
114
|
+
else:
|
|
115
|
+
verification = f"""The MCP contribution is `{contribution_path(metadata)}`. Its generated Python
|
|
116
|
+
tests validate contribution metadata and native registration:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
python -m pytest {test_path(metadata)}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Follow the [native validation sequence](https://github.com/hashgraph-online/hol-guard/blob/main/docs/guard/extension-builder/VALIDATION.md)
|
|
123
|
+
to regenerate and verify the complete catalog after integration.
|
|
124
|
+
"""
|
|
102
125
|
return f"""# {safe_name}: Guard contribution kit
|
|
103
126
|
|
|
104
127
|
This is generated contributor knowledge, not a security certificate. The extension
|
|
@@ -108,7 +131,13 @@ validation never run the target or change Guard policy.
|
|
|
108
131
|
## Review first
|
|
109
132
|
|
|
110
133
|
Read `report.json` and inspect every operation against the upstream implementation.
|
|
111
|
-
|
|
134
|
+
Copy the review file from this kit's parent directory:
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
cp KIT/review.json REVIEW.json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Edit `REVIEW.json`. Changed behavior needs
|
|
112
141
|
`reviewed: true`, rationale, and an HTTPS evidence reference. Names, descriptions,
|
|
113
142
|
help flags, and MCP annotations do not establish safety. Unknown CLI invocations
|
|
114
143
|
retain review; unknown MCP tools inherit existing Guard handling.
|
|
@@ -116,21 +145,29 @@ retain review; unknown MCP tools inherit existing Guard handling.
|
|
|
116
145
|
Recompile edits into a new directory from this kit's parent directory:
|
|
117
146
|
|
|
118
147
|
```sh
|
|
119
|
-
hol-guard extensions generate --from snapshot --input KIT/discovery.json --review
|
|
148
|
+
hol-guard extensions generate --from snapshot --input KIT/discovery.json --review REVIEW.json --output REVIEWED_KIT
|
|
120
149
|
hol-guard extensions validate REVIEWED_KIT
|
|
121
150
|
hol-guard extensions apply REVIEWED_KIT --repo /path/to/hol-guard
|
|
122
151
|
```
|
|
123
152
|
|
|
124
|
-
Replace `KIT`, `REVIEWED_KIT`, and the checkout path with your actual paths.
|
|
125
|
-
|
|
126
|
-
`--expected-plan PLAN_DIGEST
|
|
153
|
+
Replace `KIT`, `REVIEW.json`, `REVIEWED_KIT`, and the checkout path with your actual paths.
|
|
154
|
+
Edit the copied review file before running snapshot generation. Inspect the plan,
|
|
155
|
+
then apply with `--expected-plan PLAN_DIGEST --write` using its printed digest.
|
|
156
|
+
Apply never commits, activates, or submits a PR.
|
|
127
157
|
Existing manual edits are conflicts, not permission to overwrite work.
|
|
128
158
|
|
|
129
159
|
## Native verification in the destination checkout
|
|
130
160
|
|
|
161
|
+
Stage the shared review resources before running contribution tests:
|
|
162
|
+
|
|
131
163
|
```sh
|
|
132
164
|
python scripts/release/stage_guard_cloud_review_artifacts.py
|
|
133
|
-
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
{verification}
|
|
168
|
+
Run the shared contribution checks:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
134
171
|
python -m pytest tests/test_guard_extension_contribution.py tests/test_guard_mcp_server_contribution.py
|
|
135
172
|
```
|
|
136
173
|
|
|
@@ -17,7 +17,9 @@ from .errors import BuilderError
|
|
|
17
17
|
from .io import canonical_json, checked_path, parse_json, read_bytes
|
|
18
18
|
from .models import Metadata
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
LISTING_SCHEMA_V1 = "guard.extension-listing.v1"
|
|
21
|
+
LISTING_SCHEMA_V2 = "guard.extension-listing.v2"
|
|
22
|
+
LISTING_SCHEMA = LISTING_SCHEMA_V2
|
|
21
23
|
MAX_LISTING_BYTES = 16_384
|
|
22
24
|
MAX_TAGLINE_LENGTH = 140
|
|
23
25
|
CATEGORY_LABELS = {
|
|
@@ -36,9 +38,15 @@ DEFAULT_LIMITATIONS = (
|
|
|
36
38
|
)
|
|
37
39
|
|
|
38
40
|
|
|
39
|
-
@lru_cache(maxsize=
|
|
40
|
-
def listing_schema() -> dict[str, object]:
|
|
41
|
-
|
|
41
|
+
@lru_cache(maxsize=2)
|
|
42
|
+
def listing_schema(schema_version: str = LISTING_SCHEMA) -> dict[str, object]:
|
|
43
|
+
filename = {
|
|
44
|
+
LISTING_SCHEMA_V1: "listing.v1.schema.json",
|
|
45
|
+
LISTING_SCHEMA_V2: "listing.v2.schema.json",
|
|
46
|
+
}.get(schema_version)
|
|
47
|
+
if filename is None:
|
|
48
|
+
raise BuilderError("listing_schema", "Listing uses an unsupported metadata schema version.")
|
|
49
|
+
payload = files("codex_plugin_scanner.guard.extension_builder").joinpath(filename)
|
|
42
50
|
return cast(dict[str, object], json.loads(payload.read_text(encoding="utf-8")))
|
|
43
51
|
|
|
44
52
|
|
|
@@ -72,7 +80,10 @@ def _public_https(value: str) -> None:
|
|
|
72
80
|
def validate_listing(payload: object, *, expected_id: str | None = None) -> dict[str, object]:
|
|
73
81
|
"""Validate bounded listing metadata without resolving links or performing a claim grant."""
|
|
74
82
|
|
|
75
|
-
|
|
83
|
+
schema_version = payload.get("schemaVersion") if isinstance(payload, dict) else None
|
|
84
|
+
if not isinstance(schema_version, str) or schema_version not in {LISTING_SCHEMA_V1, LISTING_SCHEMA_V2}:
|
|
85
|
+
raise BuilderError("listing_schema", "Listing uses an unsupported metadata schema version.")
|
|
86
|
+
validator = Draft202012Validator(listing_schema(cast(str, schema_version)), format_checker=FormatChecker())
|
|
76
87
|
try:
|
|
77
88
|
validator.validate(payload)
|
|
78
89
|
except (ValidationError, RecursionError) as exc:
|
|
@@ -80,7 +91,15 @@ def validate_listing(payload: object, *, expected_id: str | None = None) -> dict
|
|
|
80
91
|
row = cast(dict[str, object], payload)
|
|
81
92
|
if expected_id is not None and row["extensionId"] != expected_id:
|
|
82
93
|
raise BuilderError("listing_identity", "Listing identity must match its native contribution and filename.")
|
|
83
|
-
|
|
94
|
+
text_values = [row["tagline"], *cast(list[str], row["limitations"])]
|
|
95
|
+
upstream: dict[str, object] | None = None
|
|
96
|
+
if schema_version == LISTING_SCHEMA_V2:
|
|
97
|
+
text_values.append(row["summary"])
|
|
98
|
+
raw_upstream = row["upstream"]
|
|
99
|
+
if raw_upstream is not None:
|
|
100
|
+
upstream = cast(dict[str, object], raw_upstream)
|
|
101
|
+
text_values.append(cast(str, cast(dict[str, object], upstream)["name"]))
|
|
102
|
+
for value in text_values:
|
|
84
103
|
if (
|
|
85
104
|
not isinstance(value, str)
|
|
86
105
|
or value != value.strip()
|
|
@@ -90,6 +109,21 @@ def validate_listing(payload: object, *, expected_id: str | None = None) -> dict
|
|
|
90
109
|
reference = row.get("documentationUrl")
|
|
91
110
|
if isinstance(reference, str):
|
|
92
111
|
_public_https(reference)
|
|
112
|
+
if schema_version == LISTING_SCHEMA_V2:
|
|
113
|
+
contributors = cast(list[dict[str, object]], row["contributors"])
|
|
114
|
+
if len({str(item["githubId"]) for item in contributors}) != len(contributors):
|
|
115
|
+
raise BuilderError("listing_contributors", "Contributor GitHub identities must be unique.")
|
|
116
|
+
for contributor in contributors:
|
|
117
|
+
roles = cast(list[str], contributor["roles"])
|
|
118
|
+
if len(set(roles)) != len(roles):
|
|
119
|
+
raise BuilderError("listing_contributors", "Contributor credit roles must be unique.")
|
|
120
|
+
references = cast(list[dict[str, object]], row["originalContributions"])
|
|
121
|
+
if len({str(item["url"]) for item in references}) != len(references):
|
|
122
|
+
raise BuilderError("listing_references", "Original contribution references must be unique.")
|
|
123
|
+
for item in references:
|
|
124
|
+
_public_https(cast(str, item["url"]))
|
|
125
|
+
if upstream is not None:
|
|
126
|
+
_public_https(cast(str, cast(dict[str, object], upstream)["url"]))
|
|
93
127
|
if len(canonical_json(row).encode("utf-8")) > MAX_LISTING_BYTES:
|
|
94
128
|
raise BuilderError("listing_limit", "Listing exceeds its byte budget.")
|
|
95
129
|
return row
|
|
@@ -111,6 +145,10 @@ def listing_template(metadata: Metadata) -> str:
|
|
|
111
145
|
"tagline": f"Reviewed operation coverage for {metadata.name}."[:MAX_TAGLINE_LENGTH].rstrip(),
|
|
112
146
|
"category": "specialized-tools" if metadata.kind == "mcp" else "other",
|
|
113
147
|
"limitations": list(DEFAULT_LIMITATIONS),
|
|
148
|
+
"summary": f"Reviewed operation coverage for {metadata.name} through the native Guard contract.",
|
|
149
|
+
"contributors": [],
|
|
150
|
+
"originalContributions": [],
|
|
151
|
+
"upstream": None,
|
|
114
152
|
}
|
|
115
153
|
try:
|
|
116
154
|
_public_https(metadata.homepage)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://hol.org/guard/contracts/extension-listing.v2.schema.json",
|
|
4
|
+
"title": "HOL Guard extension contributor listing metadata",
|
|
5
|
+
"description": "Bounded public credit and provenance metadata. contributors is attribution only; maintainerGithubIds remains separately reviewed claim-authority input and validation does not grant authority.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"schemaVersion",
|
|
10
|
+
"extensionId",
|
|
11
|
+
"tagline",
|
|
12
|
+
"category",
|
|
13
|
+
"limitations",
|
|
14
|
+
"summary",
|
|
15
|
+
"contributors",
|
|
16
|
+
"originalContributions",
|
|
17
|
+
"upstream"
|
|
18
|
+
],
|
|
19
|
+
"properties": {
|
|
20
|
+
"schemaVersion": { "const": "guard.extension-listing.v2" },
|
|
21
|
+
"extensionId": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"maxLength": 256,
|
|
24
|
+
"pattern": "^(command|mcp)\\.[a-z0-9]+(?:[.-][a-z0-9]+)*$"
|
|
25
|
+
},
|
|
26
|
+
"tagline": { "type": "string", "minLength": 10, "maxLength": 140 },
|
|
27
|
+
"summary": { "type": "string", "minLength": 20, "maxLength": 2048 },
|
|
28
|
+
"category": {
|
|
29
|
+
"enum": [
|
|
30
|
+
"core-safety",
|
|
31
|
+
"cloud-infrastructure",
|
|
32
|
+
"data-resilience",
|
|
33
|
+
"delivery-remote",
|
|
34
|
+
"managed-services",
|
|
35
|
+
"package-supply-chain",
|
|
36
|
+
"specialized-tools",
|
|
37
|
+
"other"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"limitations": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"minItems": 1,
|
|
43
|
+
"maxItems": 8,
|
|
44
|
+
"uniqueItems": true,
|
|
45
|
+
"items": { "type": "string", "minLength": 10, "maxLength": 400 }
|
|
46
|
+
},
|
|
47
|
+
"documentationUrl": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 10,
|
|
50
|
+
"maxLength": 1024,
|
|
51
|
+
"pattern": "^https://",
|
|
52
|
+
"format": "uri"
|
|
53
|
+
},
|
|
54
|
+
"tags": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"maxItems": 8,
|
|
57
|
+
"uniqueItems": true,
|
|
58
|
+
"items": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"minLength": 2,
|
|
61
|
+
"maxLength": 30,
|
|
62
|
+
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"maintainerGithubIds": {
|
|
66
|
+
"description": "Reviewed numeric GitHub IDs authorized to manage a publisher profile. Credits and pull-request authorship never grant this authority.",
|
|
67
|
+
"type": "array",
|
|
68
|
+
"maxItems": 8,
|
|
69
|
+
"uniqueItems": true,
|
|
70
|
+
"items": { "type": "string", "pattern": "^[1-9][0-9]{0,19}$" }
|
|
71
|
+
},
|
|
72
|
+
"contributors": {
|
|
73
|
+
"description": "Public credit only. These identities cannot authorize a claim.",
|
|
74
|
+
"type": "array",
|
|
75
|
+
"maxItems": 8,
|
|
76
|
+
"items": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"additionalProperties": false,
|
|
79
|
+
"required": ["githubId", "githubLogin", "roles"],
|
|
80
|
+
"properties": {
|
|
81
|
+
"githubId": { "type": "string", "pattern": "^[1-9][0-9]{0,19}$" },
|
|
82
|
+
"githubLogin": {
|
|
83
|
+
"type": "string",
|
|
84
|
+
"minLength": 1,
|
|
85
|
+
"maxLength": 100,
|
|
86
|
+
"pattern": "^[A-Za-z0-9](?:[A-Za-z0-9-]{0,98}[A-Za-z0-9])?$"
|
|
87
|
+
},
|
|
88
|
+
"roles": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"minItems": 1,
|
|
91
|
+
"maxItems": 3,
|
|
92
|
+
"uniqueItems": true,
|
|
93
|
+
"items": { "enum": ["author", "co-author", "reviewer", "maintainer"] }
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"originalContributions": {
|
|
99
|
+
"type": "array",
|
|
100
|
+
"maxItems": 8,
|
|
101
|
+
"items": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"required": ["kind", "url"],
|
|
105
|
+
"properties": {
|
|
106
|
+
"kind": { "enum": ["pull-request", "issue", "commit", "discussion"] },
|
|
107
|
+
"url": { "type": "string", "minLength": 10, "maxLength": 1024, "pattern": "^https://", "format": "uri" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"upstream": {
|
|
112
|
+
"anyOf": [
|
|
113
|
+
{ "type": "null" },
|
|
114
|
+
{
|
|
115
|
+
"type": "object",
|
|
116
|
+
"additionalProperties": false,
|
|
117
|
+
"required": ["name", "url"],
|
|
118
|
+
"properties": {
|
|
119
|
+
"name": { "type": "string", "minLength": 2, "maxLength": 160 },
|
|
120
|
+
"url": { "type": "string", "minLength": 10, "maxLength": 1024, "pattern": "^https://", "format": "uri" }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
codex_plugin_scanner/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
|
|
5
5
|
Project-URL: Homepage, https://hol.org/guard
|
|
6
6
|
Project-URL: Security, https://hol.org/guard/security
|
|
@@ -167,7 +167,7 @@ hol-guard command extensions command.git --json
|
|
|
167
167
|
|
|
168
168
|
`command test` and `command explain` inspect the command without executing it or creating an approval. Use `hol-guard approvals` to resolve a pending request and `hol-guard receipts` to review the recorded decision.
|
|
169
169
|
|
|
170
|
-
The [Extension directory](docs/guard/extensions/README.md) lists command coverage generated from the
|
|
170
|
+
The [Extension directory](docs/guard/extensions/README.md) lists command coverage generated from the Rust-compiled catalog. External contributions require explicit opt-in; required core protections remain enabled. To add coverage, follow the [Extension contribution guide](docs/guard/extensions/contributing.md).
|
|
171
171
|
|
|
172
172
|
### Check a package
|
|
173
173
|
|
|
@@ -424,6 +424,7 @@ The action may need approval under your active policy, or its tools or artifacts
|
|
|
424
424
|
| [Policy specification](spec/guard-policy/v1alpha1/README.md) | GuardPolicy document format. |
|
|
425
425
|
| [Policy recipes](docs/guard/policy-recipes.md) | Configuration examples for common workflows. |
|
|
426
426
|
| [Extensions](docs/guard/extensions/README.md) | Built-in command rules and contribution guidance. |
|
|
427
|
+
| [Native extension authoring](docs/guard/extension-builder/README.md) | Canonical JSON sources, the Rust compiler, portable fixtures, and review kits. |
|
|
427
428
|
| [Contribute an extension](#contribute-a-new-extension) | Generate, review, integrate, and test a new extension with the CLI. |
|
|
428
429
|
| [Local vs. cloud](docs/guard/local-vs-cloud.md) | Local capabilities and optional cloud services. |
|
|
429
430
|
| [Troubleshooting](docs/guard/troubleshooting.md) | Diagnosis and recovery. |
|
|
@@ -431,7 +432,17 @@ The action may need approval under your active policy, or its tools or artifacts
|
|
|
431
432
|
|
|
432
433
|
## Contribute a New Extension
|
|
433
434
|
|
|
434
|
-
|
|
435
|
+
Command extensions are authored as **declarative JSON compiled and evaluated by Rust**. Add metadata, permissions, matcher trees, and safe variants in `contributions/command-sources/command.<name>.json`, then verify behavior with portable JSON fixtures. Most extensions compose existing native operations; a new Rust operation is needed only when the existing matcher contracts cannot express the behavior.
|
|
436
|
+
|
|
437
|
+
| Contribution | Authoring input | Verification |
|
|
438
|
+
| :--- | :--- | :--- |
|
|
439
|
+
| Command coverage | `contributions/command-sources/command.<name>.json` | Portable fixtures evaluated by `guard-command-source test`. |
|
|
440
|
+
| MCP server knowledge | `contributions/mcp-servers/<id>.json` | MCP contribution tests and native catalog validation. |
|
|
441
|
+
| New matcher semantics | Reviewed Rust changes in `rust/crates/guard-command/` | Native contract, admission, evaluation, and regression tests. |
|
|
442
|
+
|
|
443
|
+
The Rust compiler generates command descriptors, the catalog, and the native matcher program. Python remains part of the CLI, build orchestration, and tests; new command coverage does not require a Python detector or registry registration. See the [authoring guide](docs/guard/extension-builder/README.md) for direct source authoring and the [architecture](docs/guard/command-extension-architecture.md) for the runtime boundary.
|
|
444
|
+
|
|
445
|
+
The **Extension Builder CLI** can create those command sources and portable fixtures from exported command metadata. It also supports MCP inventories. It works offline and reads the export without importing or running the target tool.
|
|
435
446
|
|
|
436
447
|
**1. Propose the coverage.** Check the [Extension directory](docs/guard/extensions/README.md) for existing coverage. For a new capability, open an [Extension proposal](https://github.com/hashgraph-online/hol-guard/issues/new?template=command-extension-proposal.yml) with the proposed `command.<name>` ID, supported operations, destructive examples, safe counterparts, and upstream references. Extend an existing extension when it already owns the operation.
|
|
437
448
|
|
|
@@ -450,7 +461,7 @@ uv run --no-sync hol-guard extensions generate --from cli \
|
|
|
450
461
|
uv run --no-sync hol-guard extensions validate samplectl-kit
|
|
451
462
|
```
|
|
452
463
|
|
|
453
|
-
The output directory must be new, with an existing parent directory.
|
|
464
|
+
The output directory must be new, with an existing parent directory. A command kit includes `discovery.json`, `review.json`, `report.json`, the canonical JSON source, a portable native fixture, a generated descriptor, and a file manifest. MCP kits contain their contribution metadata and generated Python tests.
|
|
454
465
|
|
|
455
466
|
Other inputs: `--from help` reads saved command help; `--from click` reads a Click `Context.to_info_dict()` export; `--from oclif` reads `oclif.manifest.json`; `--from mcp` reads a complete exported `tools/list` result; and `--from snapshot` replays `discovery.json`. The `cli` example above uses normalized `guard.cli-surface.v1` JSON.
|
|
456
467
|
|
|
@@ -464,7 +475,7 @@ cp samplectl-kit/review.json samplectl-review.json
|
|
|
464
475
|
|
|
465
476
|
Edit `samplectl-review.json`, keeping its discovery binding and operation IDs intact. CLI operations use `review` or `block`; the root operation stays `review`. Set `reviewed: true` for entries you have assessed, with rationale and a public HTTPS evidence reference. Add `safeArgv` only for exact, verified safe invocations. The [review format](docs/guard/extension-builder/README.md#review-and-recompile) includes a complete entry example.
|
|
466
477
|
|
|
467
|
-
Recompile
|
|
478
|
+
Recompile the saved snapshot after reviewing it:
|
|
468
479
|
|
|
469
480
|
```bash
|
|
470
481
|
uv run --no-sync hol-guard extensions generate --from snapshot \
|
|
@@ -473,9 +484,12 @@ uv run --no-sync hol-guard extensions generate --from snapshot \
|
|
|
473
484
|
|
|
474
485
|
uv run --no-sync hol-guard extensions validate samplectl-reviewed
|
|
475
486
|
uv run --no-sync hol-guard extensions diff samplectl-kit samplectl-reviewed
|
|
487
|
+
|
|
488
|
+
"$HOL_GUARD_NATIVE_SOURCE_COMPILER" test \
|
|
489
|
+
< samplectl-reviewed/artifacts/tests/fixtures/command-source-samplectl.v1.json
|
|
476
490
|
```
|
|
477
491
|
|
|
478
|
-
`diff` exits `0` for equal kits and `1` when valid kits differ. If the upstream export changes, generate and review a new snapshot.
|
|
492
|
+
`diff` exits `0` for equal kits and `1` when valid kits differ. The Rust fixture runner evaluates command text without executing it. If the upstream export changes, generate and review a new snapshot.
|
|
479
493
|
|
|
480
494
|
**4. Preview and apply the integration.** On your contribution branch, preview the changes to the current checkout:
|
|
481
495
|
|
|
@@ -491,25 +505,27 @@ uv run --no-sync hol-guard extensions apply samplectl-reviewed --repo . \
|
|
|
491
505
|
--write
|
|
492
506
|
```
|
|
493
507
|
|
|
494
|
-
The write
|
|
508
|
+
The write integrates the canonical source, fixture, generated contribution descriptor, external trust map, packaging, and authoring ownership records. Regenerate the complete program and catalog in the next step. Existing IDs or conflicting files stop integration for review.
|
|
495
509
|
|
|
496
|
-
**5. Test and submit a pull request.**
|
|
510
|
+
**5. Test and submit a pull request.** Follow the [native validation sequence](docs/guard/extension-builder/VALIDATION.md) to regenerate the complete catalog, rebuild the compiler and runtime against that program, and run the contribution's fixtures against the integrated sources. This also covers updating an existing extension, where an addition to the packaged baseline would conflict with the existing ID. Then run the contribution checks and regenerate the public directory:
|
|
497
511
|
|
|
498
512
|
```bash
|
|
499
513
|
uv run --no-sync python scripts/release/stage_guard_cloud_review_artifacts.py
|
|
500
|
-
uv run --no-sync pytest -q tests/test_generated_cli_samplectl_extension.py
|
|
501
514
|
uv run --no-sync pytest -q \
|
|
502
515
|
tests/test_guard_extension_contribution.py \
|
|
503
516
|
tests/test_guard_extension_trust.py \
|
|
517
|
+
tests/test_native_source_program.py \
|
|
504
518
|
tests/test_guard_command_extension_registry.py
|
|
519
|
+
uv run --no-sync python scripts/export_extension_directory.py
|
|
520
|
+
uv run --no-sync python scripts/export_extension_directory.py --check
|
|
505
521
|
uv run --no-sync python scripts/render_command_extension_directory.py
|
|
506
522
|
uv run --no-sync python scripts/render_command_extension_directory.py --check
|
|
507
523
|
git diff --check
|
|
508
524
|
```
|
|
509
525
|
|
|
510
|
-
|
|
526
|
+
Add fixture cases for destructive operations, safe previews, aliases, reordered flags, quoting, malformed input, and compound commands. Run the Rust checks when changing native semantics and the relevant Python checks when changing tooling. Inspect the final diff, commit the canonical inputs, generated projections, fixtures, and authoring records, and open a PR against `main` linking the proposal and test results. Keep scratch kit directories and raw upstream exports out of the PR.
|
|
511
527
|
|
|
512
|
-
**Community contributions remain External and off by default.** Tests must prove they are inert until a local administrator enables them. Generating, applying, or merging a contribution does not activate it, and its
|
|
528
|
+
**Community contributions remain External and off by default.** Tests must prove they are inert until a local administrator enables them. Generating, applying, or merging a contribution does not activate it, and its rules cannot weaken Guard's required protections.
|
|
513
529
|
|
|
514
530
|
[Full builder reference](docs/guard/extension-builder/README.md) · [Contribution review requirements](docs/guard/extensions/contributing.md) · [External extension contract](docs/guard/extension-contributions.md) · [Builder validation](docs/guard/extension-builder/VALIDATION.md)
|
|
515
531
|
|
|
@@ -517,15 +533,35 @@ Use your generated test filename for a different slug. Add cases for destructive
|
|
|
517
533
|
|
|
518
534
|
## Development
|
|
519
535
|
|
|
520
|
-
|
|
536
|
+
The development toolchain includes Python 3.10 or newer, [uv](https://docs.astral.sh/uv/), and Rust 1.88.0, pinned in [`rust/rust-toolchain.toml`](rust/rust-toolchain.toml). Rust builds the native runtime and extension compiler; Python supplies the CLI and development tooling. The commands below use a POSIX shell from the repository root. See [CONTRIBUTING.md](CONTRIBUTING.md) for Windows setup and the checks for each kind of change.
|
|
521
537
|
|
|
522
538
|
```bash
|
|
523
539
|
git clone https://github.com/hashgraph-online/hol-guard.git
|
|
524
540
|
cd hol-guard
|
|
525
|
-
uv sync --extra dev
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
541
|
+
uv sync --frozen --extra dev
|
|
542
|
+
rustup toolchain install 1.88.0 --profile minimal --component rustfmt --component clippy
|
|
543
|
+
cargo +1.88.0 build --locked --release --manifest-path rust/Cargo.toml \
|
|
544
|
+
-p guard-command --bin guard-command-source
|
|
545
|
+
cargo +1.88.0 build --locked --release --manifest-path rust/Cargo.toml \
|
|
546
|
+
-p hol-guard-runtime
|
|
547
|
+
|
|
548
|
+
export HOL_GUARD_NATIVE_SOURCE_COMPILER="$PWD/rust/target/release/guard-command-source"
|
|
549
|
+
export HOL_GUARD_NATIVE_TEST_SOURCE_COMPILER="$HOL_GUARD_NATIVE_SOURCE_COMPILER"
|
|
550
|
+
export HOL_GUARD_NATIVE_BINARY="$PWD/rust/target/release/hol-guard-runtime"
|
|
551
|
+
|
|
552
|
+
uv run --no-sync python scripts/build_native_command_program.py \
|
|
553
|
+
--compiler "$HOL_GUARD_NATIVE_SOURCE_COMPILER" --check
|
|
554
|
+
uv run --no-sync pytest tests/test_guard_extension_builder_public_docs.py \
|
|
555
|
+
tests/test_native_source_program.py --tb=short
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
Those compiler overrides are for an editable checkout. Installed native wheels use their bundled compiler and verify its manifest. After changing canonical sources or Rust semantics, regenerate the projections and rebuild as described in the [validation guide](docs/guard/extension-builder/VALIDATION.md).
|
|
559
|
+
|
|
560
|
+
For Python tooling and package changes:
|
|
561
|
+
|
|
562
|
+
```bash
|
|
563
|
+
uv run --no-sync ruff check src tests
|
|
564
|
+
uv run --no-sync ruff format --check src tests
|
|
529
565
|
uv build
|
|
530
566
|
```
|
|
531
567
|
|
|
@@ -41,7 +41,7 @@ codex_plugin_scanner/trust_scoring.py,sha256=t_Lw13HZ766UCJzTtNNwllZK_k2ks_x-8St
|
|
|
41
41
|
codex_plugin_scanner/trust_skill_scoring.py,sha256=e-SrMBgAruzFn4RD0pGpP9rtPXxc2ji_CKpcnFPRh3M,12542
|
|
42
42
|
codex_plugin_scanner/trust_specs.py,sha256=aYGSB8M9RQp1uwhsRaWlVa1M9Vk51kUIxmBXkW8noZU,10729
|
|
43
43
|
codex_plugin_scanner/verification.py,sha256=iVYDMyqjLQjD2KlnROTu4_sPLb_WyH8kFN-BOqR2kWM,33689
|
|
44
|
-
codex_plugin_scanner/version.py,sha256=
|
|
44
|
+
codex_plugin_scanner/version.py,sha256=uEdlQ680Q1mo3cw9jrleVlG3awmY6R3gi2Sk3ATSjYo,98
|
|
45
45
|
codex_plugin_scanner/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
codex_plugin_scanner/checks/best_practices.py,sha256=uB3DXLggqxjfyBMH_1yvX4nyFhpIvaRHjTyyueoO-GQ,8473
|
|
47
47
|
codex_plugin_scanner/checks/claude.py,sha256=DeKUbGPt2McSGhijzXLPL_SzjG_15WAB35_7mk8LU5A,10938
|
|
@@ -746,9 +746,10 @@ codex_plugin_scanner/guard/extension_builder/__init__.py,sha256=61jWiLq4RNyk8unD
|
|
|
746
746
|
codex_plugin_scanner/guard/extension_builder/discover.py,sha256=BfBSKiA9ZreYaa0Vkqsc7EqPtk530eVqUG8QrMJpVds,2114
|
|
747
747
|
codex_plugin_scanner/guard/extension_builder/errors.py,sha256=rJKUHDGfaXY1yeGsHuC6B9jN3Afzi1qGO0PDn6jiTRE,525
|
|
748
748
|
codex_plugin_scanner/guard/extension_builder/io.py,sha256=iwIO_RmFeIxt0XYADLSiHL2XwtWrDEvSfAK_Q3A7gkE,5732
|
|
749
|
-
codex_plugin_scanner/guard/extension_builder/kit.py,sha256
|
|
750
|
-
codex_plugin_scanner/guard/extension_builder/listing.py,sha256=
|
|
749
|
+
codex_plugin_scanner/guard/extension_builder/kit.py,sha256=-vNBmONMBZG3PiaFqj6Z-PrSBH0U-XGqMxMP94Pyix0,16546
|
|
750
|
+
codex_plugin_scanner/guard/extension_builder/listing.py,sha256=Rfm6kLkGu9HJM89NvN1BO4JS7_FshO_OSZH9lJkmK20,8931
|
|
751
751
|
codex_plugin_scanner/guard/extension_builder/listing.v1.schema.json,sha256=TEWEVboGa0JtcJoImDI0z-VfZ_WCUNwjBV8pDoz6oBg,2278
|
|
752
|
+
codex_plugin_scanner/guard/extension_builder/listing.v2.schema.json,sha256=87UMlr3UC4vbZv-wwhebVBBBachoSPelPOA8VLcajFk,3944
|
|
752
753
|
codex_plugin_scanner/guard/extension_builder/listing_cli.py,sha256=CSFEtNcsT0TC-J4WYhbKJKT3mpX-fcBJB87EuQ63ldU,1102
|
|
753
754
|
codex_plugin_scanner/guard/extension_builder/models.py,sha256=iGX7HyEcFq78MAqQO5Nj6ye5mqKHtwtWsqL5_iklzmE,9155
|
|
754
755
|
codex_plugin_scanner/guard/extension_builder/native_source_compiler.py,sha256=f_VerXp0pdrMBjMx-aajix3y41M5tFgLQ4pU0eZXfkY,20196
|
|
@@ -1289,8 +1290,8 @@ codex_plugin_scanner/guard/contracts/data/guard-cloud-review/v2/contract.json,sh
|
|
|
1289
1290
|
codex_plugin_scanner/guard/contracts/data/guard-cloud-review/v2/fixtures.json,sha256=vpf8NvLxmgI9ISG_mnSo5bBGYsegO4cZDwOIXmictfk,20769
|
|
1290
1291
|
codex_plugin_scanner/guard/contracts/data/mcp_servers/contributions/mcp.filesystem.json,sha256=dgKScdJ07v8m_7S028oAKd_D0awf8tmKXWtdWWjtICc,1270
|
|
1291
1292
|
codex_plugin_scanner/guard/contracts/data/mcp_servers/contributions/mcp.instapods.json,sha256=4pfklIwGN3vg3PHEW-aDr2Bql6sCv_oApQMmgk5SzlY,1449
|
|
1292
|
-
plugin_scanner-3.
|
|
1293
|
-
plugin_scanner-3.
|
|
1294
|
-
plugin_scanner-3.
|
|
1295
|
-
plugin_scanner-3.
|
|
1296
|
-
plugin_scanner-3.
|
|
1293
|
+
plugin_scanner-3.3.0.dist-info/METADATA,sha256=RqE_b6mxky0mJ3YgcuqqBPEX6QkSfEfQCurAfbIeSEk,34909
|
|
1294
|
+
plugin_scanner-3.3.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
1295
|
+
plugin_scanner-3.3.0.dist-info/entry_points.txt,sha256=SLGKi3GvvSsPwave-k2JQt2meG0pM7aaC6VlUy47Crg,122
|
|
1296
|
+
plugin_scanner-3.3.0.dist-info/licenses/LICENSE,sha256=UbiP0-niTtzc4d0UWk_KLc0SkRQH8AsG36b_YA-XM8E,11358
|
|
1297
|
+
plugin_scanner-3.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|