From 08d3b18be443cbf7a96832f3db52097607edf28e Mon Sep 17 00:00:00 2001 From: Fahmi Harun <34875577+kuker24@users.noreply.github.com> Date: Sun, 4 Oct 2026 22:09:03 +0700 Subject: [PATCH] fix(0.1.14): crawl4ai pin, finish design-bank fallback retirement, playwright config path --- CHANGELOG.md | 10 ++++++ README.md | 2 +- VERSION | 2 +- docs/CATALOG-FREEZE.md | 3 +- lib/design_v2/bootstrap.py | 39 ++------------------- lib/doctor.py | 3 +- manual-skills/reflect/references/correct.md | 2 +- rules/00-routing.md | 2 +- skills/playwright-qa/SKILL.md | 2 +- skills/playwright-qa/references/workflow.md | 2 +- tests/test_design_bootstrap.py | 38 +++++--------------- tests/test_v2_schema.py | 5 +++ vendor/license-audit.json | 2 +- vendor/provenance.json | 11 +++--- vendor/sources.json | 4 +-- 15 files changed, 44 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 585a21c..39757ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 0.1.14 — 2026-10-04 + +Patch rilis pasca-0.1.13 untuk koreksi pin sumber, penuntasan pensiun fallback Design Bank, dan perbaikan path config Playwright. Katalog tetap 65 (50 model + 15 manual). Closed intents tetap 25. Tidak ada penambahan atau pensiun skill (`vendor/skill-allowlist.txt` dan `vendor/skill-policy.json` tidak berubah). + +- **Koreksi pin crawl4ai**: Memperbaiki commit SHA crawl4ai di `vendor/sources.json` yang sebelumnya salah tercatat (salah hash tip) menjadi `133e1d92e37885dfccc03ea2e3687d06c98b7ceb` sesuai rilis tag resmi `v0.9.4` (tag `a9634e9`), menyelesaikan error HTTP 422 pada resolusi commit GitHub API. Menambahkan tes invariant di `tests/test_v2_schema.py`. +- **Penuntasan pensiun Design Bank Fallback #4**: Menghapus implementasi runtime fallback GitHub dari `lib/design_v2/bootstrap.py` dan method `curl-github-release`. Kegagalan resolusi Google Drive kini langsung meneruskan `BootstrapError` asli (fail-closed) tanpa menutupi akar masalah. Memperbarui `tests/test_design_bootstrap.py` untuk menguji penjalaran error Drive tanpa fallback. Mengarahkan entri komponen `design-bank` di `vendor/provenance.json` ke pin Google Drive v3 (`lib/design_v2/bootstrap_sources.json`, `OpenCodeHighEnd-DesignBank-v3.zip`, SHA-256 `91d90b4e...`). +- **Koreksi path config Playwright QA**: Memperbaiki dokumentasi pada `skills/playwright-qa/references/workflow.md` agar merujuk ke file JSON (default `.playwright/cli.config.json`). Menegaskan bahwa emulasi timezone, locale, dan geolocation diatur secara programatik melalui `run-code`. Menyelaraskan catatan pada `skills/playwright-qa/SKILL.md` dan `rules/00-routing.md`. +- **Harmonisasi hierarki invarian reflect**: Memperjelas subjudul pada `manual-skills/reflect/references/correct.md` menjadi adaptasi 5 level OCH (upstream pstack menggabungkan types dan linter menjadi 4 level). +- **Versi Produk**: Bump versi ke `0.1.14` (`VERSION`, `vendor/sources.json`, `vendor/provenance.json`, `vendor/license-audit.json`, `README.md`, `docs/CATALOG-FREEZE.md`). + ## 0.1.13 — 2026-10-04 Wave 0.1.13 upstream sync across 6 discrete scopes (A–F). Katalog tetap 65 (50 model + 15 manual). Closed intents tetap 25. Tidak ada penambahan atau pensiun skill (`vendor/skill-allowlist.txt` dan `vendor/skill-policy.json` tidak berubah). diff --git a/README.md b/README.md index d6e980a..2310444 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ OpenCode 2 overlay: 65 frozen routed skills, thin `AGENTS.md`, `opencode-he`. Installer and runtime overlay for [OpenCode 2](https://opencode.ai/v2/docs/). -Version **0.1.13**. The 65-skill catalog is strictly frozen. +Version **0.1.14**. The 65-skill catalog is strictly frozen. ## What it is diff --git a/VERSION b/VERSION index 7ac4e5e..71d6a66 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.13 +0.1.14 diff --git a/docs/CATALOG-FREEZE.md b/docs/CATALOG-FREEZE.md index b60bd8e..e6e8a3a 100644 --- a/docs/CATALOG-FREEZE.md +++ b/docs/CATALOG-FREEZE.md @@ -2,8 +2,9 @@ This contract defines the immutable boundary and governance for the OpenCodeHighEnd catalog. The 65-skill catalog is strictly frozen. -- **Product version**: 0.1.13 +- **Product version**: 0.1.14 - **Catalog**: 65 names. 50 model-invoked under `skills/`. 15 manual under `manual-skills/` + `commands/`. +- **Wave 0.1.14 body-only**: catalog strictly frozen at 65 (50 model + 15 manual). Zero catalog growth. No new exceptions. Post-release fixes for 0.1.13: corrected crawl4ai commit pin in `vendor/sources.json` to official `v0.9.4` release (`133e1d92e37885dfccc03ea2e3687d06c98b7ceb`); completed retirement of Design Bank fallback #4 from runtime and tests with fail-closed Drive error propagation; corrected Playwright CLI config path documentation (`.playwright/cli.config.json`) and clarified timezone/locale emulation via `run-code`; aligned reflect invariant enforcement hierarchy wording (5-level OCH adaptation). - **Wave 0.1.13 body-only**: catalog strictly frozen at 65 (50 model + 15 manual). Zero catalog growth. No new exceptions. Upstream sync across 6 discrete scopes: pins updated for `shadcn@4.21.1`, `@reticlehq/server@3.5.0`, `markitdown-mcp==0.0.1a7` with `markitdown[all]==0.1.8`, `crawl4ai` `/mcp/sse`; refreshed `playwright-qa` with device emulation, media feature toggles, and WebMCP security boundaries, `install-anti-slop` with `update` mode, `scroll-craft` dual-door browser handoffs; doctrines adopted: Emil Kowalski `break-ui` adversarial UI stress testing into `skills/impeccable/reference/break-ui.md`, pstack `/correct` invariant enforcement hierarchy into `manual-skills/reflect/references/correct.md`, `motion-designer` scored review / phone review / motion blur into `business-motion-film`, `architect` agent contributor lens; attribution and governance synchronized; serena GPL-3.0-or-later boundary preserved as external pointer. - **Wave 0.1.12 body-only**: catalog strictly frozen at 65 (50 model + 15 manual). Zero catalog growth. No new exceptions. Upstream hyperframes refreshed to v0.8.119 (declarative data attributes, CLI render pipeline); awesome-opus5-5-videos added as first-party POINTER_ONLY prompt patterns reference; Matt Pocock cluster migrated to GLOSSARY.md convention with legacy CONTEXT.md fallback; dead game-asset-core references removed; humanizer bumped to v3.1.0 with patterns 25 & 26; diagram-design pinned to 2.6.51; impeccable v4.5.0 deferred. - **Wave 0.1.11 body-only**: catalog strictly frozen at 65 (50 model + 15 manual). Zero catalog growth. No new exceptions. Adds closed intent `web_research` mapped to existing skill `research` (body-only update + `references/web-data.md`). Scrapling added as optional MCP `FOREIGN_ON_DEMAND`. Agent-Reach documented as `POINTER_ONLY` host CLI. Patchright-Enhanced strictly rejected. diff --git a/lib/design_v2/bootstrap.py b/lib/design_v2/bootstrap.py index b5c4580..46e91ca 100644 --- a/lib/design_v2/bootstrap.py +++ b/lib/design_v2/bootstrap.py @@ -228,35 +228,6 @@ def operator_url_source(url: str, sha256: str) -> tuple[BootstrapSource, str]: ) -def github_fallback_source() -> tuple[BootstrapSource, str]: - path = repo_root() / "vendor" / "sources.json" - try: - payload = json.loads(path.read_text(encoding="utf-8")) - except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc: - raise BootstrapError("SOURCE_RESOLVED", "vendor sources unreadable", code="BOOTSTRAP_SOURCE_INVALID") from exc - block = ((payload.get("sources") or {}) if isinstance(payload, dict) else {}).get("design-bank") - if not isinstance(block, dict): - raise BootstrapError("SOURCE_RESOLVED", "github fallback missing", code="BOOTSTRAP_SOURCE_INVALID") - url = block.get("artifactUrl") - sha = block.get("artifactSha256") - if not isinstance(url, str) or not url.startswith("https://"): - raise BootstrapError("SOURCE_RESOLVED", "github fallback URL", code="BOOTSTRAP_SOURCE_INVALID") - if not isinstance(sha, str) or not SHA256_HEX_RE.fullmatch(sha): - raise BootstrapError("SOURCE_RESOLVED", "github fallback SHA-256", code="BOOTSTRAP_SOURCE_INVALID") - return ( - BootstrapSource( - name="github-release-fallback", - source_type="https-artifact", - bank_version=str(block.get("version") or "fallback"), - archive_name=_archive_name_from_url(url, "Design-bank.tgz"), - archive_file_id="", - checksum_file_id="", - pinned_sha256=sha.lower(), - ), - url, - ) - - def select_remote_source( source_name: str | None = None, *, config_path: Path | None = None ) -> tuple[BootstrapSource, str | None, str]: @@ -264,14 +235,8 @@ def select_remote_source( if env: source, url = operator_url_source(env[0], env[1]) return source, url, "curl-operator-url" - try: - source = resolve_bootstrap_source(source_name, config_path=config_path) - return source, None, "curl-google-drive-public" - except BootstrapError: - if source_name: - raise - source, url = github_fallback_source() - return source, url, "curl-github-release" + source = resolve_bootstrap_source(source_name, config_path=config_path) + return source, None, "curl-google-drive-public" def _is_html_file(path: Path) -> bool: diff --git a/lib/doctor.py b/lib/doctor.py index 1df7646..ab0f915 100644 --- a/lib/doctor.py +++ b/lib/doctor.py @@ -527,7 +527,8 @@ def _browser_qa_findings(f: Findings) -> None: f.add("OPTIONAL_ABSENT", "Playwright browsers", "not cached in ~/.cache/ms-playwright") project_suites = [] - for cfg_name in ("playwright.config.ts", "playwright.config.js", "cypress.config.ts", "cypress.config.js"): + e2e_candidates = [f"playwright.config.{ext}" for ext in ("ts", "js")] + ["cypress.config.ts", "cypress.config.js"] + for cfg_name in e2e_candidates: if (Path.cwd() / cfg_name).is_file(): project_suites.append(cfg_name) if project_suites: diff --git a/manual-skills/reflect/references/correct.md b/manual-skills/reflect/references/correct.md index 25598c2..73470a7 100644 --- a/manual-skills/reflect/references/correct.md +++ b/manual-skills/reflect/references/correct.md @@ -76,7 +76,7 @@ Record durable enforcements in the repository's verification or reflection notes |---|---|---|---| | _(class)_ | _(incident)_ | _(level)_ | _(check)_ | -### Enforcement rules (adapted; upstream 4 levels) +### Enforcement rules (5-level OCH adaptation; upstream pstack combines types and lint into 4 levels) - If a pattern is already common in the codebase, a test or check should fail only when a change adds more of it — not on pre-existing occurrences. - Exceptions must be documented at the relevant line with the rationale, an expiration date, and explicit human approval. diff --git a/rules/00-routing.md b/rules/00-routing.md index 726c02b..e671316 100644 --- a/rules/00-routing.md +++ b/rules/00-routing.md @@ -150,7 +150,7 @@ The specialist architecture forms a deterministic graph connected by file artifa - Photoreal stills / ads / identity with no UI surface: `/visual-studio`. - Motion after Impeccable: `/emil-design-eng`. - Image/video generation: use OpenCode native image tools if the session exposes them. Otherwise write prompt files and mark DEGRADED. Do not invent `image_gen`. -- Exploratory application UI QA: `/playwright-qa` is the primary adapter (navigation, form inputs, state inspection, snapshot, screenshot, device and viewport emulation: `--device`, `resize`, `set-color-scheme`, `set-reduced-motion`, `set-forced-colors`, `set-contrast`, `set-media`; timezone/locale/geolocation via `--config` only). Never launch for backend/non-UI. +- Exploratory application UI QA: `/playwright-qa` is the primary adapter (navigation, form inputs, state inspection, snapshot, screenshot, device and viewport emulation: `--device`, `resize`, `set-color-scheme`, `set-reduced-motion`, `set-forced-colors`, `set-contrast`, `set-media`; timezone/locale/geolocation via `run-code`). Never launch for backend/non-UI. - Explicit multi-account or persistent browser sessions: `/browser-act`. Load the skill before any `browser-act` command. Never `--type chrome-direct`. - Observed browser cause: `/chrome-devtools-axi` after `opencode-chromium-cdp start` on `http://127.0.0.1:9223`. Never Google Chrome. - Deterministic browser regression: existing project test suite (Playwright Test, Cypress, etc.) using project scripts/package manager. diff --git a/skills/playwright-qa/SKILL.md b/skills/playwright-qa/SKILL.md index 45e567b..5919f77 100644 --- a/skills/playwright-qa/SKILL.md +++ b/skills/playwright-qa/SKILL.md @@ -23,7 +23,7 @@ This skill provides an interactive, token-efficient browser interface for agents 7. **Privacy & Hygiene**: Storage state, cookies, HAR recordings, traces, and screenshots must never be committed to git or printed with sensitive credentials. 8. **No Browser for Backend**: Never start browser sessions when only backend, API, database, or non-UI code changed. 9. **No Data Gathering**: Web and social data gathering is not UI QA; route extraction tasks to `research` (`references/web-data.md`). -10. **Emulation & Responsive QA**: Emulate devices (`open --device`), resize viewports (`resize `), and toggle media features (`set-color-scheme`, `set-reduced-motion`, `set-forced-colors`, `set-contrast`, `set-media`). Timezone, locale, and geolocation require `--config` or `run-code`. +10. **Emulation & Responsive QA**: Emulate devices (`open --device`), resize viewports (`resize `), and toggle media features (`set-color-scheme`, `set-reduced-motion`, `set-forced-colors`, `set-contrast`, `set-media`). Timezone, locale, and geolocation require `run-code`. ## Workflow diff --git a/skills/playwright-qa/references/workflow.md b/skills/playwright-qa/references/workflow.md index cd2a362..450ca2d 100644 --- a/skills/playwright-qa/references/workflow.md +++ b/skills/playwright-qa/references/workflow.md @@ -64,7 +64,7 @@ Use device presets at launch and session commands to toggle media features. playwright-cli -s= set-media print playwright-cli -s= clear-media ``` -- **Timezone / Locale / Geolocation**: Not available as CLI flags. Use `--config playwright.config.ts` at launch or `run-code` to set programmatically. +- **Timezone / Locale / Geolocation**: Not available as CLI flags. Set programmatically via `run-code` (CLI `--config` accepts JSON files defaulting to `.playwright/cli.config.json`, not TypeScript config; timezone/locale emulation via config is unverified). 7. **Clean up**: ```bash diff --git a/tests/test_design_bootstrap.py b/tests/test_design_bootstrap.py index 82b2359..63de226 100644 --- a/tests/test_design_bootstrap.py +++ b/tests/test_design_bootstrap.py @@ -356,43 +356,21 @@ def test_symlink_valid_bank_is_already_present(self): self.assertEqual(payload["status"], "already_present") self.assertEqual(self.download_calls, []) - def test_github_tgz_fallback_when_drive_config_missing(self): - tgz = self.tmp / "Design-bank.tgz" - with tarfile.open(tgz, "w:gz") as handle: - handle.add(self.source_tree, arcname=".") - digest = hashlib.sha256(tgz.read_bytes()).hexdigest() - from lib.design_v2.bootstrap import BootstrapSource - - fallback = BootstrapSource( - name="github-release-fallback", - source_type="https-artifact", - bank_version="1.0.0", - archive_name="Design-bank.tgz", - archive_file_id="", - checksum_file_id="", - pinned_sha256=digest, - ) - url = "https://example.com/artifacts/Design-bank.tgz" - - def tgz_downloader(fetch_url: str, destination: Path) -> None: - self.download_calls.append(fetch_url) - destination.parent.mkdir(parents=True, exist_ok=True) - shutil.copy2(tgz, destination) - + def test_drive_failure_without_env_override_raises_original_error_without_fallback(self): missing = self.tmp / "missing-drive.json" missing.write_text('{"schemaVersion":1,"default":"missing","sources":{}}', encoding="utf-8") - with patch("lib.design_v2.bootstrap.github_fallback_source", return_value=(fallback, url)): - payload = bootstrap_design_bank( + from lib.design_v2.bootstrap import BootstrapError + + with self.assertRaises(BootstrapError) as ctx: + bootstrap_design_bank( target=self.target, design_v2_root=self.design_v2, cache_dir=self.cache, - downloader=tgz_downloader, + downloader=self._downloader, config_path=missing, ) - self.assertEqual(payload["status"], "ok") - self.assertEqual(payload["source"], "github-release-fallback") - self.assertEqual(self.download_calls, [url]) - self.assertTrue((self.target / "21st/library/catalog.json").is_file()) + self.assertEqual(ctx.exception.stage, "SOURCE_RESOLVED") + self.assertEqual(self.download_calls, []) if __name__ == "__main__": diff --git a/tests/test_v2_schema.py b/tests/test_v2_schema.py index 37b5933..f2cd714 100644 --- a/tests/test_v2_schema.py +++ b/tests/test_v2_schema.py @@ -36,6 +36,11 @@ def test_shadcn_mcp_invocation_and_pin(self): self.assertEqual(sources["version"], "4.21.1") self.assertEqual(sources["via"], "npx") + def test_crawl4ai_sources_pin(self): + sources = jsonc.load_path(ROOT / "vendor" / "sources.json")["sources"]["crawl4ai"] + self.assertEqual(sources["version"], "0.9.4") + self.assertEqual(sources["commit"], "133e1d92e37885dfccc03ea2e3687d06c98b7ceb") + def test_installer_rejects_opencode_1(self): prev = os.environ.get("OPENCODE_HE_MOCK_OPENCODE") with tempfile.TemporaryDirectory() as td: diff --git a/vendor/license-audit.json b/vendor/license-audit.json index 09c0198..3227b3a 100644 --- a/vendor/license-audit.json +++ b/vendor/license-audit.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "product": "OpenCodeHighEnd", - "productVersion": "0.1.13", + "productVersion": "0.1.14", "note": "Evidence-based. A missing frontmatter license is not a grant. Adapted \u2260 first-party.", "skills": { "demo-video": { diff --git a/vendor/provenance.json b/vendor/provenance.json index a0494f3..bf48bac 100644 --- a/vendor/provenance.json +++ b/vendor/provenance.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "product": "OpenCodeHighEnd", - "productVersion": "0.1.13", + "productVersion": "0.1.14", "firstPartyLicense": "MIT", "components": [ { @@ -175,12 +175,13 @@ }, { "component": "design-bank", - "path": "GitHub Release v1.0.0 Design-bank.tgz", - "upstream": "Refero + Motionsites catalogs packed by this project", - "version": "1.0.0", + "path": "OpenCodeHighEnd-DesignBank-v3.zip", + "upstream": "lib/design_v2/bootstrap_sources.json (Google Drive v3)", + "version": "v3", "license": "not-cleared", "modified": true, - "redistribution": "unknown" + "redistribution": "unknown", + "notes": "Bootstrap archive OpenCodeHighEnd-DesignBank-v3.zip (SHA-256 91d90b4ef9e1af9a44b222171ecb8becac521cfc0814117bdcdc08a54e86df53)." }, { "component": "diagnosing-bugs", diff --git a/vendor/sources.json b/vendor/sources.json index 4137dfb..8529172 100644 --- a/vendor/sources.json +++ b/vendor/sources.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "product": "OpenCodeHighEnd", - "productVersion": "0.1.13", + "productVersion": "0.1.14", "sources": { "codebase-memory": { "repository": "https://github.com/DeusData/codebase-memory-mcp", @@ -80,7 +80,7 @@ "crawl4ai": { "repository": "https://github.com/unclecode/crawl4ai", "version": "0.9.4", - "commit": "133e1d92e37803a60a7e1104e1388836ea4120ec", + "commit": "133e1d92e37885dfccc03ea2e3687d06c98b7ceb", "status": "foreign-on-demand", "note": "Optional remote MCP at http://127.0.0.1:11235/mcp/sse. Legacy /mcp emits WARN CRAWL4AI_LEGACY_URL." },