From edfaf76844acfcf4a91d2401966ff9f485fab7da Mon Sep 17 00:00:00 2001 From: dd3ok <15044917+dd3ok@users.noreply.github.com> Date: Sun, 5 Jul 2026 08:12:03 +0900 Subject: [PATCH 1/2] Align briefprint docs and metadata --- README.ko.md | 9 ++ README.md | 9 ++ VALIDATION.md | 99 +++++++------------ agents/openai.yaml | 4 +- docs/agent-skill-installation.md | 25 +++++ references/best-practices.md | 12 ++- references/competitive-roadmap.md | 20 +++- scripts/validate_skill.py | 2 +- skills/briefprint/agents/openai.yaml | 2 +- .../briefprint/references/best-practices.md | 2 + src/document_briefing_cache/models.py | 1 - tests/test_docs.py | 41 ++++++++ tests/test_installable_skill_bundle.py | 7 ++ tests/test_pipeline_cache.py | 15 +++ tests/test_skill_metadata.py | 12 ++- 15 files changed, 183 insertions(+), 77 deletions(-) diff --git a/README.ko.md b/README.ko.md index c07c9dd..628668a 100644 --- a/README.ko.md +++ b/README.ko.md @@ -61,6 +61,13 @@ pip install -e ".[llm]" # OpenAI 기반 구조화 요약기 pip install -e ".[pdf]" # PDF 텍스트 추출 helper ``` +이름 안내: + +- 에이전트 스킬: `briefprint` +- Python 패키지/CLI: `document-briefing-cache` / `document_briefing_cache` + +런타임 이름은 패키지 호환성을 위해 유지하고, 설치 가능한 에이전트 스킬은 Briefprint로 브랜딩합니다. + 샘플 실행: ```bash @@ -213,6 +220,8 @@ python -m document_briefing_cache.cli run \ `--redact-secrets`는 `basic-secrets-v1` 프로필을 적용합니다. bearer tokens, API keys, webhook URLs, card-like values, secret-shaped JSON keys를 best-effort로 가립니다. Secret redaction is not included in --sensitive; 민감 문서에 비밀값이 들어갈 수 있으면 별도로 켜야 합니다. +`--redact-secrets`는 `session_id`처럼 운영 상관관계 분석에 쓰이는 값도 secret-shaped key 아래에 있으면 가릴 수 있습니다. 정확한 추적보다 비밀값 보호가 더 중요한 경우에 켜세요. + `--cache-hmac-secret-env`는 HMAC-SHA256으로 캐시 envelope을 서명합니다. HMAC은 tamper detection only, not encryption 입니다. 캐시 내용 자체를 숨겨야 한다면 encrypted storage, tmpfs, 또는 별도 암호화 저장소를 사용해야 합니다. 캐시 관리: diff --git a/README.md b/README.md index 3952822..30d08dd 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,13 @@ pip install -e ".[llm]" # OpenAI-backed structured summarizer pip install -e ".[pdf]" # PDF text extraction helpers ``` +Naming note: + +- Agent skill: `briefprint` +- Python package/CLI: `document-briefing-cache` / `document_briefing_cache` + +The runtime names are kept for package compatibility while the installable agent skill is branded as Briefprint. + Run the sample: ```bash @@ -213,6 +220,8 @@ For sensitive documents, the safe default is no persistent cache. `--sensitive` `--redact-secrets` applies the built-in `basic-secrets-v1` profile. It is best-effort and targets bearer tokens, API keys, webhook URLs, card-like values, and string values under secret-shaped JSON keys. Secret redaction is not included in --sensitive; enable it explicitly when secret-shaped values may appear. +`--redact-secrets` may also remove operational correlation values such as `session_id` when they appear under secret-shaped keys. Enable it when secret protection matters more than exact operational correlation. + `--cache-hmac-secret-env` signs cache envelopes with HMAC-SHA256. HMAC is tamper detection only, not encryption. Use encrypted storage, tmpfs, or another encrypted backend when cache contents need confidentiality. Cache maintenance: diff --git a/VALIDATION.md b/VALIDATION.md index d23c4d5..e9bd15f 100644 --- a/VALIDATION.md +++ b/VALIDATION.md @@ -1,91 +1,64 @@ # Validation -Last verified: 2026-05-14 +Last verified: 2026-07-04 -Environment: +## Environment -- Python 3.14.4 -- Source-tree validation used the local Python environment with pytest available. -- Pytest capture used `TMPDIR=/tmp` so temp files are created on a POSIX filesystem. -- Local `python3 -m build` was unavailable in this environment (`No module named build`). +- Python 3.13.14 +- pytest 9.0.3 +- ruff 0.15.15 +- Source-tree validation used the local Python environment. -Commands: +## Commands -```bash -TMPDIR=/tmp PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 -m pytest -q -PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 scripts/validate_skill.py --run-evals -TMPDIR=/tmp PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=src python3 -m pytest tests/test_distribution_smoke.py -q +```powershell +$env:PYTHONDONTWRITEBYTECODE='1' +python -m pytest -q -p no:cacheprovider +python scripts\validate_skill.py --run-evals +ruff check . ``` -`tests/test_distribution_smoke.py` is opt-in and skips unless `DBC_RUN_INSTALLED_SMOKE=1` is set. The default local command above confirms the skipped source-tree test is present; it does not by itself install or smoke-test built artifacts. +## Observed Results + +- `python -m pytest -q -p no:cacheprovider`: `164 passed, 2 skipped` +- `python scripts\validate_skill.py --run-evals`: `OK: briefprint skill repository validated (24 test files, 9 eval cases, 9 trigger cases, 4 model benchmark cases)` +- `ruff check .`: `All checks passed!` -CI performs wheel and sdist artifact install smoke validation by building distributions, installing each artifact into a fresh virtual environment, and running the renderer from `/tmp` so default templates must be loaded from packaged resources rather than repository-local files. +`tests/test_distribution_smoke.py` remains opt-in and skips unless `DBC_RUN_INSTALLED_SMOKE=1` is set. CI or release validation should still build wheel and sdist artifacts, install each into a fresh virtual environment, and run the installed smoke test outside the repository root. -Local artifact smoke requires the `build` module plus explicit virtual environment install commands. Example: +Example artifact smoke flow: ```bash -python3 -m build -python3 -m venv /tmp/dbc-wheel-venv +python -m build +python -m venv /tmp/dbc-wheel-venv /tmp/dbc-wheel-venv/bin/python -m pip install dist/*.whl /tmp/dbc-wheel-venv/bin/python -m pip install pytest (cd /tmp && DBC_RUN_INSTALLED_SMOKE=1 /tmp/dbc-wheel-venv/bin/python -m pytest /path/to/repo/tests/test_distribution_smoke.py -q) -python3 -m venv /tmp/dbc-sdist-venv +python -m venv /tmp/dbc-sdist-venv /tmp/dbc-sdist-venv/bin/python -m pip install dist/*.tar.gz /tmp/dbc-sdist-venv/bin/python -m pip install pytest (cd /tmp && DBC_RUN_INSTALLED_SMOKE=1 /tmp/dbc-sdist-venv/bin/python -m pytest /path/to/repo/tests/test_distribution_smoke.py -q) ``` -Observed result: +## Validation Scope -```text -110 passed, 1 skipped -OK: briefprint skill repository validated (19 test files, 6 eval cases, 9 trigger cases, 4 model benchmark cases) -tests/test_distribution_smoke.py: 1 skipped -python3 -m build --version: No module named build -``` +The current validation covers: -Trigger evals are static boundary fixtures. They validate intended trigger coverage and near-miss cases, but they do not measure actual model-side invocation behavior. -Model invocation benchmark cases are manual worksheets for hosts that expose real invocation telemetry. +- installable `skills/briefprint/` bundle shape and metadata, +- trigger fixtures and near-miss boundaries, +- document normalization and fingerprinting, +- document cache and output cache behavior, +- cache explanation events, +- incident record splitting, +- privacy redaction and HMAC tamper-detection behavior, +- rendering and evidence preservation, +- local deterministic benchmark/eval fixtures, +- CLI and packaging smoke coverage available from the source tree. -Smoke test using `examples/mixed_documents.json` and a fresh cache: - -```text -1st run, mode=brief: - output_cache_hit: false - document_cache_hits: 0 - document_cache_misses: 3 - document_cache_corrupt: 0 - summarizer_calls: 3 - -2nd run, same mode=brief: - output_cache_hit: true - summarizer_calls: 0 - -3rd run, changed mode=action_items: - output_cache_hit: false - document_cache_hits: 3 - document_cache_misses: 0 - document_cache_corrupt: 0 - summarizer_calls: 0 -``` +Trigger evals are static boundary fixtures. They validate intended trigger coverage and near-miss cases, but they do not measure actual model-side invocation behavior. -Expected properties: - -- The skill metadata exists in `SKILL.md`. -- Trigger boundaries avoid source-code review, live lookup, and non-document Q&A. -- Trigger evals separately cover positive document-briefing cases and negative boundary cases. -- The implementation has deterministic document fingerprints. -- Repeated documents are served from document-level cache. -- Re-rendering from another template does not trigger re-summarization. -- Cached summaries are rejected when fingerprint, schema, document id, or summarizer id does not match. -- Cache envelopes require payload digests and private POSIX permissions where the filesystem supports them. -- HMAC-signed cache envelopes reject payload, cache-version, and expiry metadata tampering when configured. -- Signed cache reads fail closed without the HMAC secret; prune skips unverifiable signed entries instead of deleting them. -- Basic contact PII redaction runs before cache-miss summarization and separates redacted/non-redacted cache keys. -- Rendered Markdown escapes untrusted document/model fields. -- The default rules summarizer can run without an LLM or network access. -- The repository includes templates, references, tests, examples, evals, and a CLI. +Model invocation benchmark cases are manual worksheets for hosts that expose real invocation telemetry. Production validation should continue adding real samples from the target domain and compare: diff --git a/agents/openai.yaml b/agents/openai.yaml index 3fdd024..fa2aea7 100644 --- a/agents/openai.yaml +++ b/agents/openai.yaml @@ -2,7 +2,7 @@ version: "0.3.1" interface: display_name: "Briefprint" - short_description: "Read once. Brief anywhere. Reuse structured document briefings from fingerprinted cache." + short_description: "Rerender cached document briefings without re-summarizing unchanged supplied documents." default_prompt: "Use $briefprint to summarize the supplied documents into a cached briefing and include cache stats." policy: @@ -31,6 +31,6 @@ metadata: - "Do not use for source-code review or debugging." - "Do not use when there is no document-like input to cache or rerender." privacy: - - "rules mode is local and token-free." + - "Rules mode is local and token-free when the runtime provides it." - "LLM-backed modes send cache misses to the configured provider." - "Cache files may contain names, IDs, dates, metrics, sources, and evidence quotes." diff --git a/docs/agent-skill-installation.md b/docs/agent-skill-installation.md index 71b8ba9..f60f3c2 100644 --- a/docs/agent-skill-installation.md +++ b/docs/agent-skill-installation.md @@ -1,5 +1,15 @@ # Lightweight Agent Skill Installation +Last checked: 2026-07-04 + +## Verified surfaces + +These notes cover Codex, Claude Code, Gemini CLI, Antigravity, OpenClaw, and Hermes install surfaces for the lightweight `skills/briefprint` bundle. + +## Community-compatible notes + +Community host commands below are examples to verify against the current host documentation before use. Prefer any current host option that installs the `skills/briefprint` subdirectory without copying the repository root. + This repository has two different install surfaces: - Python package/runtime: installs `document_briefing_cache` code and templates. @@ -24,6 +34,21 @@ skills/briefprint/ It intentionally excludes `tests`, `docs`, `examples`, `evals`, `src`, and `scripts`. +## Verify installed files + +After installation, the skill directory should contain only these files: + +```text +SKILL.md +agents/openai.yaml +references/architecture.md +references/schema.md +references/llm-contract.md +references/best-practices.md +``` + +It must not contain development or runtime directories such as `.github`, `docs`, `evals`, `examples`, `scripts`, `src`, or `tests`. + ## Codex Codex skills use a directory containing `SKILL.md`. Codex reads only skill metadata at startup, then loads `SKILL.md` and referenced files progressively when the skill is relevant. diff --git a/references/best-practices.md b/references/best-practices.md index f600698..d67ec17 100644 --- a/references/best-practices.md +++ b/references/best-practices.md @@ -59,18 +59,22 @@ Keep a separate manual benchmark worksheet for actual model-side invocation beha Document summaries can contain evidence quotes, names, IDs, dates, metrics, sources, and rendered outputs. Prefer private cache permissions, short output-cache TTLs, and `ephemeral` mode for sensitive documents. -For sensitive documents, the safe default is no persistent cache: +For sensitive documents, use the convenience alias unless you need to spell out each flag: ```bash python -m document_briefing_cache.cli run \ --input sensitive.json \ - --cache-policy ephemeral \ - --no-output-cache \ - --redact-pii + --sensitive ``` +`--sensitive` expands to `--cache-policy ephemeral --no-output-cache --redact-pii --delete-on-exit created`. + Use `--redact-pii` when basic contact information should not reach LLM cache-miss calls or local cache files. Redaction is a profile, so include its policy id in document and output cache keys. The built-in `basic-contact-v1` redaction profile covers common email addresses, Korean mobile numbers, and US phone numbers. It is not a complete PII detector for names, addresses, national IDs, account numbers, cards, API keys, or access tokens. +Use `--redact-secrets` when bearer tokens, API keys, webhook URLs, card-like values, or string values under secret-shaped JSON keys may appear. It applies the built-in `basic-secrets-v1` profile. Secret redaction is best-effort and is not included in `--sensitive`; enable it explicitly when secrecy matters more than preserving exact operational identifiers. + +Secret redaction may remove operational correlation values such as `session_id` when they appear under secret-shaped keys. Do not enable it for workflows where exact correlation IDs are more important than masking likely secrets. + Use HMAC-signed cache envelopes when local tamper detection matters. Sign the payload and security-relevant metadata such as namespace, key, cache version, payload digest, and expiry. HMAC signing is tamper detection only, not encryption; cache files remain plaintext unless the deployment provides encrypted storage, tmpfs, or another encrypted backend. Pass the HMAC secret to cache maintenance commands that need to verify signed entries. Without the secret, maintenance should skip signed entries instead of pruning them as corrupt. diff --git a/references/competitive-roadmap.md b/references/competitive-roadmap.md index 5d0e362..351ced8 100644 --- a/references/competitive-roadmap.md +++ b/references/competitive-roadmap.md @@ -1,8 +1,8 @@ # Competitive Roadmap -Status: proposed -Last reviewed: 2026-07-03 -Scope: lightweight roadmap for keeping this repository a compact exact-cache document briefing skill. +Status: implemented through P5; deferred items remain +Last reviewed: 2026-07-04 +Scope: lightweight status record for keeping this repository a compact exact-cache document briefing skill. ## Position @@ -21,6 +21,19 @@ The competitive wedge is not a broader document platform, RAG system, semantic c Every roadmap item should strengthen one of those claims without making `SKILL.md` or the runtime surface heavy. +## Current implementation status + +| Item | Status | Evidence | +| --- | --- | --- | +| P0 Demo-first lifecycle | Implemented | `examples/incident_lifecycle/` and benchmark docs exist. | +| P1 Cache explain / document cache trace | Implemented | `PipelineStats.document_cache_events`, `PipelineStats.output_cache_event`, and CLI `--explain-cache` exist. | +| P2 Narrow incident record splitting | Implemented as incident-only slice | CLI supports `--split-records incident`; broader parsers remain out of scope. | +| P3 Workflow and nuance evals | Implemented | `evals/briefing_eval_cases.json` includes nuance fixtures for status, absence-of-evidence wording, and communication restrictions. | +| P4 Skill metadata tightening | Implemented | Metadata exists and uses a routing-oriented short description. | +| P5 Sensitive preset | Implemented | `--sensitive` is a thin alias; `--redact-secrets` remains explicit. | + +The items below that remain deferred or rejected should not be added without new failing fixtures, a clear user need, and a separate plan. + ## Evidence Reviewed Repository evidence: @@ -160,7 +173,6 @@ class DocumentCacheEvent(BaseModel): "miss_cache_disabled", "expired_ttl", "corrupt_validation_failed", - "corrupt_hmac_failed", "rejected_contract_mismatch", ] summarizer_id: str diff --git a/scripts/validate_skill.py b/scripts/validate_skill.py index 28ae8fd..5237b63 100644 --- a/scripts/validate_skill.py +++ b/scripts/validate_skill.py @@ -256,7 +256,7 @@ def validate_openai_yaml(path: Path) -> list[str]: 'version: "0.3.1"', "interface:", 'display_name: "Briefprint"', - 'short_description: "Read once. Brief anywhere. Reuse structured document briefings from fingerprinted cache."', + 'short_description: "Rerender cached document briefings without re-summarizing unchanged supplied documents."', "$briefprint", "policy:", "allow_implicit_invocation: true", diff --git a/skills/briefprint/agents/openai.yaml b/skills/briefprint/agents/openai.yaml index a89d5ac..fa2aea7 100644 --- a/skills/briefprint/agents/openai.yaml +++ b/skills/briefprint/agents/openai.yaml @@ -2,7 +2,7 @@ version: "0.3.1" interface: display_name: "Briefprint" - short_description: "Read once. Brief anywhere. Reuse structured document briefings from fingerprinted cache." + short_description: "Rerender cached document briefings without re-summarizing unchanged supplied documents." default_prompt: "Use $briefprint to summarize the supplied documents into a cached briefing and include cache stats." policy: diff --git a/skills/briefprint/references/best-practices.md b/skills/briefprint/references/best-practices.md index faf3a22..49e7dd2 100644 --- a/skills/briefprint/references/best-practices.md +++ b/skills/briefprint/references/best-practices.md @@ -35,3 +35,5 @@ Token estimates from a local harness are not provider billing telemetry. Use pro Document summaries can contain evidence quotes, names, IDs, dates, metrics, sources, and rendered outputs. Prefer private cache permissions, short output-cache TTLs, and ephemeral mode for sensitive documents. Use redaction before cache-miss summarization when documents may contain PII or secrets. Use encrypted storage or tmpfs when cache contents need confidentiality. HMAC detects tampering only; it does not hide contents. + +Secret redaction can mask operational correlation IDs such as `session_id`; enable it only when secret protection outweighs exact correlation. diff --git a/src/document_briefing_cache/models.py b/src/document_briefing_cache/models.py index 3e6ee01..fe4e823 100644 --- a/src/document_briefing_cache/models.py +++ b/src/document_briefing_cache/models.py @@ -162,7 +162,6 @@ class DocumentCacheEvent(BaseModel): "miss_cache_disabled", "expired_ttl", "corrupt_validation_failed", - "corrupt_hmac_failed", "rejected_contract_mismatch", ] summarizer_id: str diff --git a/tests/test_docs.py b/tests/test_docs.py index 03e2163..3e61706 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -94,3 +94,44 @@ def test_readme_documents_secret_redaction_scope_and_sensitive_boundary(): assert "secret-shaped JSON keys" in readme assert "best-effort" in readme assert "not included in --sensitive" in readme + + +def test_root_best_practices_documents_sensitive_and_secret_redaction(): + best_practices = (ROOT / "references" / "best-practices.md").read_text(encoding="utf-8") + + assert "--sensitive" in best_practices + assert "--redact-secrets" in best_practices + assert "basic-secrets-v1" in best_practices + assert "not included in `--sensitive`" in best_practices + assert "HMAC signing is tamper detection only, not encryption" in best_practices + + +def test_competitive_roadmap_status_is_not_stale_proposed_snapshot(): + roadmap = (ROOT / "references" / "competitive-roadmap.md").read_text(encoding="utf-8") + + assert "Status: implemented through P5; deferred items remain" in roadmap + assert "Current implementation status" in roadmap + + +def test_readmes_document_skill_and_runtime_naming_boundary(): + readme = (ROOT / "README.md").read_text(encoding="utf-8") + korean = (ROOT / "README.ko.md").read_text(encoding="utf-8") + + assert "Agent skill: `briefprint`" in readme + assert "Python package/CLI: `document-briefing-cache` / `document_briefing_cache`" in readme + assert "에이전트 스킬: `briefprint`" in korean + assert "Python 패키지/CLI: `document-briefing-cache` / `document_briefing_cache`" in korean + + +def test_secret_redaction_docs_warn_about_operational_correlation_ids(): + readme = (ROOT / "README.md").read_text(encoding="utf-8") + korean = (ROOT / "README.ko.md").read_text(encoding="utf-8") + best_practices = (ROOT / "references" / "best-practices.md").read_text(encoding="utf-8") + skill_best_practices = (ROOT / "skills" / "briefprint" / "references" / "best-practices.md").read_text(encoding="utf-8") + + assert "session_id" in readme + assert "operational correlation" in readme + assert "session_id" in korean + assert "운영 상관관계" in korean + assert "session_id" in best_practices + assert "session_id" in skill_best_practices diff --git a/tests/test_installable_skill_bundle.py b/tests/test_installable_skill_bundle.py index bacf056..aad0cda 100644 --- a/tests/test_installable_skill_bundle.py +++ b/tests/test_installable_skill_bundle.py @@ -71,6 +71,13 @@ def test_agent_skill_installation_doc_covers_lightweight_vendor_paths(): assert "~/.codex/skills" not in doc assert "npx skills install" not in doc assert "npx skills add" in doc + for section in [ + "Verified surfaces", + "Community-compatible notes", + "Last checked: 2026-07-04", + "Verify installed files", + ]: + assert section in doc for vendor in ["Codex", "Claude Code", "Gemini CLI", "Antigravity", "OpenClaw", "Hermes"]: assert vendor in doc diff --git a/tests/test_pipeline_cache.py b/tests/test_pipeline_cache.py index c0f148e..9362357 100644 --- a/tests/test_pipeline_cache.py +++ b/tests/test_pipeline_cache.py @@ -241,3 +241,18 @@ def test_schema_100_cached_summary_is_treated_as_miss_after_v11(tmp_path): assert result.stats.document_cache_hits == 0 assert result.stats.document_cache_misses == 1 assert result.stats.summarizer_calls == 1 + + +def test_corrupt_document_cache_event_uses_validation_failed_reason(tmp_path): + doc = DocumentInput(document_id="corrupt-doc", title="Corrupt", text="Action: owner should inspect cache.") + pipeline = BriefingPipeline(cache_dir=tmp_path) + first = pipeline.run([doc], use_output_cache=False) + key = first.stats.cache_keys[next(name for name in first.stats.cache_keys if name.startswith("document:"))] + path = pipeline.document_cache.path_for(key) + path.write_text("{not-json", encoding="utf-8") + + result = BriefingPipeline(cache_dir=tmp_path).run([doc], use_output_cache=False) + + assert result.stats.document_cache_corrupt == 1 + assert result.stats.document_cache_events[0].status == "corrupt" + assert result.stats.document_cache_events[0].reason == "corrupt_validation_failed" diff --git a/tests/test_skill_metadata.py b/tests/test_skill_metadata.py index aba562d..73cf174 100644 --- a/tests/test_skill_metadata.py +++ b/tests/test_skill_metadata.py @@ -6,6 +6,9 @@ ROOT = Path(__file__).resolve().parents[1] SKILL = ROOT / "skills" / "briefprint" / "SKILL.md" +OPENAI_SHORT_DESCRIPTION = ( + 'short_description: "Rerender cached document briefings without re-summarizing unchanged supplied documents."' +) def test_versions_are_synchronized_to_0_3_1(): @@ -23,13 +26,20 @@ def test_openai_yaml_uses_interface_metadata(): assert "interface:" in openai_yaml assert 'display_name: "Briefprint"' in openai_yaml - assert 'short_description: "Read once. Brief anywhere. Reuse structured document briefings from fingerprinted cache."' in openai_yaml + assert OPENAI_SHORT_DESCRIPTION in openai_yaml assert "$briefprint" in openai_yaml assert 'name: "briefprint"' in openai_yaml assert "policy:" in openai_yaml assert "allow_implicit_invocation: true" in openai_yaml +def test_root_and_installable_openai_yaml_are_identical(): + root_openai_yaml = (ROOT / "agents" / "openai.yaml").read_bytes() + installable_openai_yaml = (ROOT / "skills" / "briefprint" / "agents" / "openai.yaml").read_bytes() + + assert root_openai_yaml == installable_openai_yaml + + def test_skill_description_matches_supported_modes_and_boundary(): skill = SKILL.read_text(encoding="utf-8") From f699a74c1bd19a1f488454f644a3e90ebf422f8a Mon Sep 17 00:00:00 2001 From: dd3ok <15044917+dd3ok@users.noreply.github.com> Date: Sun, 5 Jul 2026 08:17:02 +0900 Subject: [PATCH 2/2] Address PR review test robustness --- docs/agent-skill-installation.md | 8 +++++++- tests/test_installable_skill_bundle.py | 4 +++- tests/test_pipeline_cache.py | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/agent-skill-installation.md b/docs/agent-skill-installation.md index f60f3c2..18afae4 100644 --- a/docs/agent-skill-installation.md +++ b/docs/agent-skill-installation.md @@ -4,10 +4,16 @@ Last checked: 2026-07-04 ## Verified surfaces -These notes cover Codex, Claude Code, Gemini CLI, Antigravity, OpenClaw, and Hermes install surfaces for the lightweight `skills/briefprint` bundle. +- Codex local and repository skill folders +- Claude Code personal and project skill folders ## Community-compatible notes +- Gemini CLI +- Antigravity +- OpenClaw +- Hermes + Community host commands below are examples to verify against the current host documentation before use. Prefer any current host option that installs the `skills/briefprint` subdirectory without copying the repository root. This repository has two different install surfaces: diff --git a/tests/test_installable_skill_bundle.py b/tests/test_installable_skill_bundle.py index aad0cda..031dd7a 100644 --- a/tests/test_installable_skill_bundle.py +++ b/tests/test_installable_skill_bundle.py @@ -74,10 +74,12 @@ def test_agent_skill_installation_doc_covers_lightweight_vendor_paths(): for section in [ "Verified surfaces", "Community-compatible notes", - "Last checked: 2026-07-04", "Verify installed files", ]: assert section in doc + assert re.search(r"Last checked: \d{4}-\d{2}-\d{2}", doc) + assert "Codex local and repository skill folders" in doc + assert "Claude Code personal and project skill folders" in doc for vendor in ["Codex", "Claude Code", "Gemini CLI", "Antigravity", "OpenClaw", "Hermes"]: assert vendor in doc diff --git a/tests/test_pipeline_cache.py b/tests/test_pipeline_cache.py index 9362357..11ce89b 100644 --- a/tests/test_pipeline_cache.py +++ b/tests/test_pipeline_cache.py @@ -247,7 +247,9 @@ def test_corrupt_document_cache_event_uses_validation_failed_reason(tmp_path): doc = DocumentInput(document_id="corrupt-doc", title="Corrupt", text="Action: owner should inspect cache.") pipeline = BriefingPipeline(cache_dir=tmp_path) first = pipeline.run([doc], use_output_cache=False) - key = first.stats.cache_keys[next(name for name in first.stats.cache_keys if name.startswith("document:"))] + doc_keys = [name for name in first.stats.cache_keys if name.startswith("document:")] + assert len(doc_keys) == 1 + key = first.stats.cache_keys[doc_keys[0]] path = pipeline.document_cache.path_for(key) path.write_text("{not-json", encoding="utf-8")