Release v1.0.107: precipitate bind.selectionMode contract
All checks were successful
技能自动化发布 / release (push) Successful in 5s
All checks were successful
技能自动化发布 / release (push) Successful in 5s
This commit is contained in:
@@ -74,7 +74,7 @@ def _validate_bind_tables(action_id: str, bind: object) -> list[str]:
|
||||
errors: list[str] = []
|
||||
if not isinstance(bind, dict):
|
||||
return [f"{action_id}: bind must be object"]
|
||||
allowed = {"tables", "inputMapping", "columnMapping", "labelColumn"}
|
||||
allowed = {"tables", "inputMapping", "columnMapping", "labelColumn", "selectionMode"}
|
||||
unknown = set(bind.keys()) - allowed
|
||||
if unknown:
|
||||
errors.append(f"{action_id}: bind only allows {sorted(allowed)}, got {sorted(bind.keys())}")
|
||||
@@ -98,6 +98,11 @@ def _validate_bind_tables(action_id: str, bind: object) -> list[str]:
|
||||
errors.append(f"{action_id}: bind.labelColumn must be non-empty string")
|
||||
elif not _TABLE_NAME_PATTERN.fullmatch(label_column):
|
||||
errors.append(f"{action_id}: bind.labelColumn {label_column!r} must be snake_case")
|
||||
selection_mode = bind.get("selectionMode")
|
||||
if selection_mode is not None and selection_mode not in ("required", "none", "optional"):
|
||||
errors.append(
|
||||
f"{action_id}: bind.selectionMode must be required|none|optional, got {selection_mode!r}"
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
@@ -470,6 +475,53 @@ class TestActionsManifest(unittest.TestCase):
|
||||
}
|
||||
jsonschema.validate(instance=manifest, schema=schema)
|
||||
|
||||
def test_schema_allows_bind_selection_mode(self) -> None:
|
||||
try:
|
||||
import jsonschema
|
||||
except ImportError:
|
||||
self.fail("jsonschema is required")
|
||||
schema = _load_actions_schema()
|
||||
bind_props = schema["$defs"]["bind"]["properties"]
|
||||
self.assertIn("selectionMode", bind_props)
|
||||
self.assertEqual(
|
||||
bind_props["selectionMode"].get("enum"),
|
||||
["required", "none", "optional"],
|
||||
)
|
||||
manifest = {
|
||||
"schemaVersion": 1,
|
||||
"skill": "your-skill-slug",
|
||||
"actions": [
|
||||
{
|
||||
"id": "probe-selection-mode",
|
||||
"label": "处理队列",
|
||||
"description": "验证 bind.selectionMode 可通过 Schema",
|
||||
"placements": ["toolbar", "batch"],
|
||||
"executionProfile": "async",
|
||||
"interaction": "form",
|
||||
"bind": {
|
||||
"tables": ["demo_items"],
|
||||
"selectionMode": "optional",
|
||||
"inputMapping": {"itemIds": "$selection.ids"},
|
||||
"labelColumn": "display_name",
|
||||
},
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"required": ["itemIds", "pickCount"],
|
||||
"properties": {
|
||||
"itemIds": {"type": "string", "readOnly": True},
|
||||
"pickCount": {"type": "number", "default": 1, "minimum": 1},
|
||||
},
|
||||
},
|
||||
"entrypoint": {
|
||||
"type": "cli",
|
||||
"command": "process",
|
||||
"args": ["--ids", "{{itemIds}}", "--pick", "{{pickCount}}"],
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
jsonschema.validate(instance=manifest, schema=schema)
|
||||
|
||||
def test_no_execution_profile_placement_coupling_in_tests(self) -> None:
|
||||
"""守护:本文件不得引入入口位置与 sync/async 的错误硬耦合断言。"""
|
||||
path = os.path.join(get_skill_root(), "tests", "test_actions_manifest.py")
|
||||
@@ -632,6 +684,8 @@ class TestActionsManifest(unittest.TestCase):
|
||||
"cellPresentation",
|
||||
"CELL_PRESENTATION.md",
|
||||
"labelColumn",
|
||||
"selectionMode",
|
||||
"勾选驱动",
|
||||
"已选择",
|
||||
"revealInForm",
|
||||
"映射只读",
|
||||
|
||||
@@ -415,14 +415,18 @@ class TestDocsStandards(unittest.TestCase):
|
||||
def test_visible_when_example_is_listed(self) -> None:
|
||||
text = self._read("assets/examples/README.md")
|
||||
self.assertIn("visible-when-action.example.json", text)
|
||||
self.assertIn("selection-mode-optional.action.example.json", text)
|
||||
checklist = self._read("development/CHECKLIST.md")
|
||||
self.assertIn("A4-7", checklist)
|
||||
self.assertIn("visibleWhen", checklist)
|
||||
self.assertIn("A4-8", checklist)
|
||||
self.assertIn("revealInForm", checklist)
|
||||
self.assertIn("A4-9", checklist)
|
||||
self.assertIn("selectionMode", checklist)
|
||||
runtime = self._read("development/SKILL_ACTION_RUNTIME.md")
|
||||
self.assertIn("visibleWhen", runtime)
|
||||
self.assertIn("revealInForm", runtime)
|
||||
self.assertIn("selectionMode", runtime)
|
||||
|
||||
def test_guarded_docs_do_not_reference_amazon_implementation(self) -> None:
|
||||
forbidden = (
|
||||
|
||||
Reference in New Issue
Block a user