Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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, 또는 별도 암호화 저장소를 사용해야 합니다.

캐시 관리:
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
99 changes: 36 additions & 63 deletions VALIDATION.md
Original file line number Diff line number Diff line change
@@ -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:

Expand Down
4 changes: 2 additions & 2 deletions agents/openai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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."
31 changes: 31 additions & 0 deletions docs/agent-skill-installation.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Lightweight Agent Skill Installation

Last checked: 2026-07-04

## Verified surfaces

- 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:

- Python package/runtime: installs `document_briefing_cache` code and templates.
Expand All @@ -24,6 +40,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.
Expand Down
12 changes: 8 additions & 4 deletions references/best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 16 additions & 4 deletions references/competitive-roadmap.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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:
Expand Down Expand Up @@ -160,7 +173,6 @@ class DocumentCacheEvent(BaseModel):
"miss_cache_disabled",
"expired_ttl",
"corrupt_validation_failed",
"corrupt_hmac_failed",
"rejected_contract_mismatch",
]
summarizer_id: str
Expand Down
2 changes: 1 addition & 1 deletion scripts/validate_skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion skills/briefprint/agents/openai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions skills/briefprint/references/best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
1 change: 0 additions & 1 deletion src/document_briefing_cache/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ class DocumentCacheEvent(BaseModel):
"miss_cache_disabled",
"expired_ttl",
"corrupt_validation_failed",
"corrupt_hmac_failed",
"rejected_contract_mismatch",
]
summarizer_id: str
Expand Down
41 changes: 41 additions & 0 deletions tests/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions tests/test_installable_skill_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ 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",
"Verify installed files",
]:
assert section in doc
Comment on lines +74 to +79

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Hardcoding the exact date "Last checked: 2026-07-04" in the test assertion makes the test fragile to future documentation updates. If the documentation is updated with a new date, this test will fail. Consider using a regular expression to validate the presence of a date pattern instead.

Suggested change
for section in [
"Verified surfaces",
"Community-compatible notes",
"Last checked: 2026-07-04",
"Verify installed files",
]:
assert section in doc
for section in [
"Verified surfaces",
"Community-compatible notes",
"Verify installed files",
]:
assert section in doc
assert re.search(r"Last checked: \\d{4}-\\d{2}-\\d{2}", 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

Expand Down
Loading
Loading