fix: harden skill template contracts and scaffolding
All checks were successful
技能自动化发布 / release (push) Successful in 4s

Align scaffold slug replacement, Action manifest strict boundaries, metadata prune API, field permission validation, and task_logs readonly semantics with documented template contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-11 11:55:46 +08:00
parent 35c20fc0f2
commit 766d162245
17 changed files with 536 additions and 72 deletions

View File

@@ -2,6 +2,7 @@
"""数据管理展示元数据幂等初始化、中文名称、PRAGMA 字段顺序、校验规则。"""
from __future__ import annotations
import os
import sqlite3
import unittest
@@ -35,22 +36,39 @@ class TestDisplayMetadata(unittest.TestCase):
try:
cur = conn.cursor()
cur.execute(
"SELECT display_name FROM _jiangchang_tables WHERE table_name = 'task_logs'"
"SELECT display_name, readonly FROM _jiangchang_tables WHERE table_name = 'task_logs'"
)
self.assertEqual(cur.fetchone()[0], "任务日志")
display_name, readonly = cur.fetchone()
self.assertEqual(display_name, "任务日志")
self.assertEqual(int(readonly), 1)
cur.execute(
"""
SELECT column_name, display_name
SELECT column_name, display_name, editable
FROM _jiangchang_columns
WHERE table_name = 'task_logs'
ORDER BY column_name
"""
)
by_name = dict(cur.fetchall())
self.assertEqual(by_name["status"], "状态")
self.assertEqual(by_name["error_msg"], "错误信息")
self.assertEqual(by_name["created_at"], "创建时间")
by_name = {row[0]: (row[1], row[2]) for row in cur.fetchall()}
self.assertEqual(by_name["status"][0], "状态")
self.assertEqual(int(by_name["status"][1]), 0)
self.assertEqual(by_name["error_msg"][0], "错误信息")
self.assertEqual(int(by_name["error_msg"][1]), 0)
self.assertEqual(by_name["created_at"][0], "创建时间")
self.assertEqual(int(by_name["created_at"][1]), 0)
finally:
conn.close()
def test_task_logs_not_manual_create_in_host_ui(self) -> None:
with IsolatedDataRoot():
from db.connection import get_conn, init_db
from db.display_metadata import table_allows_manual_create
init_db()
conn = get_conn()
try:
self.assertFalse(table_allows_manual_create(conn.cursor(), "task_logs"))
finally:
conn.close()
@@ -342,6 +360,153 @@ metadata:
)
self.assertTrue(any("id" in item for item in warnings))
def test_generated_column_editable_must_be_zero(self) -> None:
conn = sqlite3.connect(":memory:")
try:
conn.executescript(
"""
CREATE TABLE gen_demo (
id INTEGER PRIMARY KEY,
base_value INTEGER NOT NULL,
generated_value INTEGER GENERATED ALWAYS AS (base_value * 2) STORED
);
"""
)
from db.display_metadata import init_display_metadata_tables, upsert_column_metadata
from db.display_metadata_validator import validate_column_permissions
cur = conn.cursor()
init_display_metadata_tables(cur)
upsert_column_metadata(
cur,
table_name="gen_demo",
column_name="generated_value",
display_name="生成值",
editable=1,
)
conn.commit()
errors, _ = validate_column_permissions(cur, "gen_demo")
self.assertTrue(any("generated" in err for err in errors))
finally:
conn.close()
def test_blob_column_editable_must_be_zero(self) -> None:
conn = sqlite3.connect(":memory:")
try:
conn.execute(
"CREATE TABLE blob_demo (id INTEGER PRIMARY KEY, payload BLOB NOT NULL)"
)
from db.display_metadata import init_display_metadata_tables, upsert_column_metadata
from db.display_metadata_validator import validate_column_permissions
cur = conn.cursor()
init_display_metadata_tables(cur)
upsert_column_metadata(
cur,
table_name="blob_demo",
column_name="payload",
display_name="载荷",
editable=1,
)
conn.commit()
errors, _ = validate_column_permissions(cur, "blob_demo")
self.assertTrue(any("BLOB" in err for err in errors))
finally:
conn.close()
def test_primary_key_editable_must_be_zero(self) -> None:
conn = sqlite3.connect(":memory:")
try:
conn.execute("CREATE TABLE pk_demo (id INTEGER PRIMARY KEY, title TEXT)")
from db.display_metadata import init_display_metadata_tables, upsert_column_metadata
from db.display_metadata_validator import validate_column_permissions
cur = conn.cursor()
init_display_metadata_tables(cur)
upsert_column_metadata(
cur,
table_name="pk_demo",
column_name="id",
display_name="编号",
editable=1,
)
conn.commit()
errors, _ = validate_column_permissions(cur, "pk_demo")
self.assertTrue(any("主键" in err for err in errors))
finally:
conn.close()
def test_readonly_table_with_editable_fields_warns(self) -> None:
conn = sqlite3.connect(":memory:")
try:
conn.executescript(
"""
CREATE TABLE warn_demo (id INTEGER PRIMARY KEY, title TEXT);
"""
)
from db.display_metadata import (
init_display_metadata_tables,
upsert_column_metadata,
upsert_table_metadata,
)
from db.display_metadata_validator import validate_column_permissions
cur = conn.cursor()
init_display_metadata_tables(cur)
upsert_table_metadata(cur, table_name="warn_demo", display_name="警告演示", readonly=1)
upsert_column_metadata(
cur,
table_name="warn_demo",
column_name="title",
display_name="标题",
editable=1,
)
conn.commit()
_, warnings = validate_column_permissions(cur, "warn_demo")
self.assertTrue(any("readonly=1" in item for item in warnings))
finally:
conn.close()
def test_writable_table_without_editable_fields_warns(self) -> None:
conn = sqlite3.connect(":memory:")
try:
conn.executescript(
"""
CREATE TABLE warn_demo2 (id INTEGER PRIMARY KEY, title TEXT);
"""
)
from db.display_metadata import (
init_display_metadata_tables,
upsert_column_metadata,
upsert_table_metadata,
)
from db.display_metadata_validator import validate_column_permissions
cur = conn.cursor()
init_display_metadata_tables(cur)
upsert_table_metadata(cur, table_name="warn_demo2", display_name="警告演示二", readonly=0)
upsert_column_metadata(
cur,
table_name="warn_demo2",
column_name="title",
display_name="标题",
editable=0,
)
conn.commit()
_, warnings = validate_column_permissions(cur, "warn_demo2")
self.assertTrue(any("readonly=0" in item and "editable=0" in item for item in warnings))
finally:
conn.close()
def test_schema_md_documents_task_logs_readonly_semantics(self) -> None:
path = os.path.join(get_skill_root(), "references", "SCHEMA.md")
with open(path, encoding="utf-8") as f:
text = f.read()
self.assertIn("readonly = 1", text)
self.assertIn("task_logs", text)
self.assertIn("seed_column_metadata_batch", text)
self.assertIn("valid_column_names", text)
if __name__ == "__main__":
unittest.main()