Skip to content

Commit c06057f

Browse files
committed
bump version to v3.7.0-beta
Signed-off-by: ainetx <viator@via-net.org>
1 parent 551edc8 commit c06057f

16 files changed

Lines changed: 252 additions & 170 deletions

File tree

.bootstrap/.core/schemas/workspace.schema.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@
6060
},
6161
"resolve": {
6262
"$ref": "#/$defs/resolve_config"
63+
},
64+
"validation": {
65+
"$ref": "#/$defs/validation_config"
6366
}
6467
},
6568
"$defs": {
@@ -139,6 +142,22 @@
139142
"description": "Maps Git host to local directory template via exact host match. Keys are hostnames, values are path templates with {org} and {repo} placeholders. When no rule matches, the default template {org}/{repo} is used. Example: {\"gitlab.com\": \"{org}/{repo}\"}."
140143
}
141144
}
145+
},
146+
"validation_config": {
147+
"type": "object",
148+
"additionalProperties": false,
149+
"description": "Artifact content validation settings.",
150+
"properties": {
151+
"allowed_content_languages": {
152+
"type": "array",
153+
"items": {
154+
"type": "string",
155+
"enum": ["en", "ru", "ar", "zh", "ja", "ko", "he", "hi", "th", "ka", "hy"]
156+
},
157+
"minItems": 1,
158+
"description": "Language codes permitted in Markdown artifact content. Default when absent: English only. Add codes to allow additional Unicode scripts (e.g. [\"en\", \"ru\"])."
159+
}
160+
}
142161
}
143162
}
144163
}

.bootstrap/.core/skills/cypilot/scripts/cypilot/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def main(argv: Optional[List[str]] = None) -> int:
1717
from .cli import main as _main
1818
return _main(argv)
1919

20-
__version__ = "v3.6.0-beta"
20+
__version__ = "v3.7.0-beta"
2121

2222
__all__ = [
2323
# Main entry point

.bootstrap/.core/skills/cypilot/scripts/cypilot/cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ def main(argv: Optional[List[str]] = None) -> int:
213213
"validate-kits": "Validate kit structure, templates, and examples",
214214
"validate-toc": "Validate Table of Contents in Markdown files",
215215
"spec-coverage": "Measure CDSL marker coverage in code",
216+
"check-language": "Check artifacts for disallowed Unicode scripts (LANG001)",
216217
"kit": "Kit management (install, update)",
217218
"init": "Initialize Cypilot in a project",
218219
"update": "Update Cypilot to the latest version",
@@ -238,7 +239,7 @@ def main(argv: Optional[List[str]] = None) -> int:
238239
}
239240
_sections = [
240241
("Setup & Configuration", ["init", "update", "info", "resolve-vars", "generate-agents", "agents"]),
241-
("Validation", ["validate", "validate-kits", "validate-toc", "spec-coverage"]),
242+
("Validation", ["validate", "validate-kits", "validate-toc", "spec-coverage", "check-language"]),
242243
("Search & Navigation", ["list-ids", "list-id-kinds", "get-content", "where-defined", "where-used"]),
243244
("Kit Management", ["kit"]),
244245
("Utility", ["toc", "chunk-input"]),

.bootstrap/.core/skills/cypilot/scripts/cypilot/commands/adapter_info.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def _load_json_file(path: Path) -> Optional[dict]:
3434
def _read_kit_conf(conf_path: Path) -> dict:
3535
"""Read kit conf.toml and return key fields."""
3636
try:
37-
3837
with open(conf_path, "rb") as f:
3938
data = tomllib.load(f)
4039
out: dict = {}
@@ -108,7 +107,6 @@ def cmd_adapter_info(argv: list[str]) -> int:
108107
registry = _load_json_file(registry_path) if registry_path.suffix == ".json" else None
109108
if registry is None and registry_path.suffix == ".toml" and registry_path.is_file():
110109
try:
111-
112110
with open(registry_path, "rb") as f:
113111
registry = tomllib.load(f)
114112
except (OSError, ValueError):

.bootstrap/.core/skills/cypilot/scripts/cypilot/commands/check_language.py

Lines changed: 73 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
"""check-language command — scan Markdown artifacts for disallowed Unicode scripts."""
1+
"""check-language command — scan Markdown artifacts for disallowed Unicode scripts.
22
3+
@cpt-algo:cpt-cypilot-flow-traceability-validation-check-language:p1
4+
"""
5+
# @cpt-begin:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-check-lang-imports
36
import argparse
47
from pathlib import Path
58
from typing import List
69

710
from ..utils import error_codes as EC
811
from ..utils.ui import ui
12+
# @cpt-end:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-check-lang-imports
913

1014

15+
# @cpt-begin:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-cmd-check-language
1116
def cmd_check_language(argv: List[str]) -> int:
1217
"""Scan Markdown files for characters outside the allowed language set.
1318
@@ -37,28 +42,25 @@ def cmd_check_language(argv: List[str]) -> int:
3742
help="Comma-separated language codes to allow, e.g. 'en' or 'en,ru'. "
3843
"Overrides workspace config.",
3944
)
40-
p.add_argument(
41-
"--exclude",
42-
action="append",
43-
default=[],
44-
metavar="GLOB",
45-
dest="exclude",
46-
help=(
47-
"Glob pattern for paths to skip (relative to each scan root). "
48-
"Repeatable: --exclude 'translations/**' --exclude 'specs/i18n/*.md'. "
49-
"Merged with check_language_ignore_paths from workspace config."
50-
),
51-
)
5245
p.add_argument(
5346
"--quiet",
5447
"-q",
5548
action="store_true",
5649
help="Suppress summary header; show violations only.",
5750
)
51+
p.add_argument(
52+
"--ignore",
53+
action="append",
54+
default=[],
55+
metavar="PATTERN",
56+
help="Glob pattern of files to skip (e.g. 'translations/**/*.md'). "
57+
"Can be repeated. Also reads ignore_paths from workspace config.",
58+
)
5859
args = p.parse_args(argv)
5960

6061
from ..utils.content_language import (
6162
SUPPORTED_LANGUAGES,
63+
LangScanError,
6264
build_allowed_ranges,
6365
scan_paths,
6466
)
@@ -78,10 +80,19 @@ def cmd_check_language(argv: List[str]) -> int:
7880
return 1
7981
allowed_langs = raw_langs
8082
else:
81-
allowed_langs = _read_config_languages()
83+
try:
84+
allowed_langs = _read_config_languages()
85+
except ValueError as exc:
86+
ui.result({"status": "ERROR", "message": str(exc)})
87+
return 1
8288

83-
# ── Resolve ignore globs ─────────────────────────────────────────────────
84-
ignore_globs: List[str] = list(args.exclude) + _read_config_ignore_paths()
89+
# ── Resolve ignore patterns ──────────────────────────────────────────────
90+
ignore_patterns: List[str] = list(args.ignore)
91+
try:
92+
ignore_patterns.extend(_read_config_ignore_patterns())
93+
except ValueError as exc:
94+
ui.result({"status": "ERROR", "message": str(exc)})
95+
return 1
8596

8697
# ── Resolve scan roots ───────────────────────────────────────────────────
8798
if args.paths:
@@ -99,14 +110,10 @@ def cmd_check_language(argv: List[str]) -> int:
99110

100111
# ── Scan ─────────────────────────────────────────────────────────────────
101112
allowed_ranges = build_allowed_ranges(allowed_langs)
102-
from ..utils.content_language import LangScanError
103113
try:
104-
violations = scan_paths(roots, allowed_ranges, ignore_globs=ignore_globs or None)
114+
violations = scan_paths(roots, allowed_ranges, ignore_patterns=ignore_patterns)
105115
except LangScanError as exc:
106-
ui.result({
107-
"status": "ERROR",
108-
"message": str(exc),
109-
})
116+
ui.result({"status": "ERROR", "message": str(exc)})
110117
return 1
111118

112119
files_scanned = _count_md_files(roots)
@@ -118,8 +125,6 @@ def cmd_check_language(argv: List[str]) -> int:
118125
"files_scanned": files_scanned,
119126
"violation_count": 0,
120127
}
121-
if ignore_globs:
122-
result["ignore_globs"] = ignore_globs
123128
ui.result(result, human_fn=lambda d: _human_result(d, quiet=args.quiet))
124129
return 0
125130

@@ -147,51 +152,58 @@ def cmd_check_language(argv: List[str]) -> int:
147152
"file_count": len(by_file),
148153
"violations": violation_items,
149154
}
150-
if ignore_globs:
151-
result["ignore_globs"] = ignore_globs
152155
ui.result(result, human_fn=lambda d: _human_result(d, quiet=args.quiet))
153156
return 2
154157

158+
# @cpt-end:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-cmd-check-language
159+
155160

156161
# ---------------------------------------------------------------------------
157162
# Helpers
158163
# ---------------------------------------------------------------------------
164+
# @cpt-begin:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-helpers
159165

160166
def _read_config_languages() -> List[str]:
161-
"""Read allowed_content_languages from workspace config; fall back to ['en']."""
162-
try:
163-
from ..utils.context import get_context
164-
from ..utils.workspace import find_workspace_config
167+
"""Read allowed_content_languages from workspace config; fall back to ['en'].
165168
166-
ctx = get_context()
167-
if ctx is None:
168-
return ["en"]
169-
_ws_cfg, _ = find_workspace_config(ctx.project_root)
170-
if _ws_cfg is not None and _ws_cfg.validation is not None: # type: ignore[union-attr]
171-
langs = _ws_cfg.validation.allowed_content_languages # type: ignore[union-attr]
172-
if langs:
173-
return langs
174-
except Exception:
175-
pass
169+
Raises ValueError if the workspace config file exists but cannot be parsed.
170+
"""
171+
from ..utils.context import get_context
172+
from ..utils.workspace import find_workspace_config
173+
174+
ctx = get_context()
175+
if ctx is None:
176+
return ["en"]
177+
_ws_cfg, _ws_err = find_workspace_config(ctx.project_root)
178+
if _ws_err:
179+
raise ValueError(f"Workspace config error: {_ws_err}")
180+
if _ws_cfg is not None and _ws_cfg.validation is not None: # type: ignore[union-attr]
181+
langs = _ws_cfg.validation.allowed_content_languages # type: ignore[union-attr]
182+
if langs:
183+
return langs
176184
return ["en"]
177185

178186

179-
def _read_config_ignore_paths() -> List[str]:
180-
"""Read check_language_ignore_paths from workspace config; fall back to []."""
181-
try:
182-
from ..utils.context import get_context
183-
from ..utils.workspace import find_workspace_config
187+
def _read_config_ignore_patterns() -> List[str]:
188+
"""Read ignore_paths glob patterns from workspace config.
184189
185-
ctx = get_context()
186-
if ctx is None:
187-
return []
188-
_ws_cfg, _ = find_workspace_config(ctx.project_root)
189-
if _ws_cfg is not None and _ws_cfg.validation is not None: # type: ignore[union-attr]
190-
paths = _ws_cfg.validation.check_language_ignore_paths # type: ignore[union-attr]
191-
if paths:
192-
return list(paths)
193-
except Exception:
194-
pass
190+
Returns an empty list when the workspace config is absent or has no
191+
ignore_paths setting. Raises ValueError if the config file cannot be
192+
parsed.
193+
"""
194+
from ..utils.context import get_context
195+
from ..utils.workspace import find_workspace_config
196+
197+
ctx = get_context()
198+
if ctx is None:
199+
return []
200+
_ws_cfg, _ws_err = find_workspace_config(ctx.project_root)
201+
if _ws_err:
202+
raise ValueError(f"Workspace config error: {_ws_err}")
203+
if _ws_cfg is not None and _ws_cfg.validation is not None: # type: ignore[union-attr]
204+
patterns = getattr(_ws_cfg.validation, "ignore_paths", None)
205+
if patterns:
206+
return list(patterns)
195207
return []
196208

197209

@@ -203,7 +215,7 @@ def _default_roots() -> List[Path]:
203215
ctx = get_context()
204216
if ctx is not None:
205217
return [ctx.project_root / "architecture"]
206-
except (ImportError, AttributeError):
218+
except (ImportError, AttributeError, RuntimeError):
207219
pass
208220
return [Path.cwd() / "architecture"]
209221

@@ -218,10 +230,13 @@ def _count_md_files(roots: List[Path]) -> int:
218230
count += sum(1 for _ in root.rglob("*.md"))
219231
return count
220232

233+
# @cpt-end:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-helpers
234+
221235

222236
# ---------------------------------------------------------------------------
223237
# Human formatter
224238
# ---------------------------------------------------------------------------
239+
# @cpt-begin:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-human-result
225240

226241
def _human_result(data: dict, quiet: bool = False) -> None:
227242
status = data.get("status", "")
@@ -266,12 +281,6 @@ def _human_result(data: dict, quiet: bool = False) -> None:
266281
" [validation]\n"
267282
" allowed_content_languages = [\"en\", \"ru\"]"
268283
)
269-
ui.hint(
270-
"To ignore specific paths (e.g. translation specs), use --exclude or add to config:\n"
271-
" [validation]\n"
272-
" check_language_ignore_paths = [\"translations/**\", \"specs/i18n/*.md\"]\n"
273-
"To ignore a single file, add <!-- cpt-lang: ignore --> anywhere in the file."
274-
)
275-
if data.get("ignore_globs"):
276-
ui.detail("Active ignore globs", ", ".join(data["ignore_globs"]))
277284
ui.blank()
285+
286+
# @cpt-end:cpt-cypilot-flow-traceability-validation-check-language:p1:inst-human-result

.bootstrap/.core/skills/cypilot/scripts/cypilot/commands/kit.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,6 @@ def _read_project_name_from_registry(config_dir: Path) -> Optional[str]:
639639
if not artifacts_toml.is_file():
640640
return None
641641
try:
642-
643642
with open(artifacts_toml, "rb") as f:
644643
data = tomllib.load(f)
645644
systems = data.get("systems", [])
@@ -1708,7 +1707,6 @@ def _read_conf_version(conf_path: Path) -> int:
17081707
if not conf_path.is_file():
17091708
return 0
17101709
try:
1711-
17121710
with open(conf_path, "rb") as f:
17131711
data = tomllib.load(f)
17141712
ver = data.get("version")
@@ -1839,7 +1837,6 @@ def _update_core_toml_kit_paths(config_dir: Path) -> None:
18391837
core_toml = config_dir / _KIT_CORE_TOML
18401838
if not core_toml.is_file():
18411839
return
1842-
18431840
with open(core_toml, "rb") as f:
18441841
data = tomllib.load(f)
18451842
kits_conf = data.get("kits", {})
@@ -2364,7 +2361,6 @@ def _read_kits_from_core_toml(config_dir: Path) -> Dict[str, Dict[str, Any]]:
23642361
if not core_toml.is_file():
23652362
return {}
23662363
try:
2367-
23682364
with open(core_toml, "rb") as f:
23692365
data = tomllib.load(f)
23702366
except (OSError, ValueError):
@@ -2385,7 +2381,6 @@ def _read_kit_slug(kit_source: Path) -> str:
23852381
if not conf_toml.is_file():
23862382
return ""
23872383
try:
2388-
23892384
with open(conf_toml, "rb") as f:
23902385
data = tomllib.load(f)
23912386
slug = data.get("slug")
@@ -2405,7 +2400,6 @@ def _read_kit_version_from_core(config_dir: Path, kit_slug: str) -> str:
24052400
if not core_toml.is_file():
24062401
return ""
24072402
try:
2408-
24092403
with open(core_toml, "rb") as f:
24102404
data = tomllib.load(f)
24112405
kit_entry = data.get("kits", {}).get(kit_slug, {})
@@ -2423,7 +2417,6 @@ def _read_kit_version(conf_path: Path) -> str:
24232417
"""Read kit version from conf.toml."""
24242418
# @cpt-begin:cpt-cypilot-algo-kit-config-helpers:p1:inst-read-kit-version
24252419
try:
2426-
24272420
with open(conf_path, "rb") as f:
24282421
data = tomllib.load(f)
24292422
ver = data.get("version")
@@ -2452,7 +2445,6 @@ def _register_kit_in_core_toml(
24522445
return
24532446

24542447
try:
2455-
24562448
with open(core_toml, "rb") as f:
24572449
data = tomllib.load(f)
24582450
except (OSError, ValueError):

.bootstrap/.core/skills/cypilot/scripts/cypilot/commands/resolve_vars.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ def cmd_resolve_vars(argv: list[str]) -> int:
334334
]:
335335
if cp.is_file():
336336
try:
337-
338337
with open(cp, "rb") as f:
339338
core_data = tomllib.load(f)
340339
except (tomllib.TOMLDecodeError, OSError) as exc:

0 commit comments

Comments
 (0)