diff --git a/CHANGELOG.md b/CHANGELOG.md index f258cd0..c0528d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,19 @@ ## [Unreleased] -- Added GitHub Actions lifecycle workflows: automated PR assignment (`.github/workflows/auto-assign.yml`), issue label synchronization (`.github/workflows/label-sync.yml`), and standard labels catalog (`.github/labels.yml`). -- Hardened CI workflow (`.github/workflows/ci.yml`) with concurrency cancellation (`cancel-in-progress: true`) and expanded Python matrix testing across versions 3.10 through 3.13. -- Created plain-text companion Level 1 SBOM `THIRD_PARTY_LICENSES.txt` certifying zero external runtime dependencies, 10 system invariants (`INV-LOCAL-01` .. `INV-SLA-10`), unprivileged `RunAsInvoker` user mode, German statutory disclaimer (§ 521 BGB Gefälligkeitsrecht), and 48h Security Response SLA. -- Standardized PEP 621 metadata in `pyproject.toml` with `Contributing`, `Plain-Text License`, and `Third-Party Licenses Text` URLs in `[project.urls]`, and configured `norecursedirs` under `[tool.pytest.ini_options]`. -- Upgraded `CONTRIBUTING.md` to a comprehensive bilingual (EN/DE) development guide including Plan D canonical local cloning instructions, Quality Gates, and Version Freeze governance. -- Hardened `.gitignore` against multi-host locks (`LOCK.dev.*`, `LOCK.antigravity.*`, `LOCK.bugsearch.*`), cloud synchronization conflicts (`*-IDEAPAD*`, `*_WORKSTATION*`, `*conflicted copy*`, `* (Kopie)*`), and scratch artifacts. -- Synchronized `llms.txt`, `MARKETING-LOG.txt`, and Shields.io badges to the 2026-10-11 audit baseline. -- Extended automated contract test suite in `tests/test_metadata.py` to cover lifecycle workflows, SBOM text companion, contributing guidelines, and multi-host gitignore defense. +- Hardened CI workflow (`.github/workflows/ci.yml`) with concurrency cancellation (`cancel-in-progress: true`) and Python matrix testing across versions 3.10 through 3.13. +- Standardized PEP 621 metadata in `pyproject.toml` with contributor and plain-text dependency-note URLs, and configured `norecursedirs` under `[tool.pytest.ini_options]`. +- Reworked `THIRD_PARTY_LICENSES.md` and `THIRD_PARTY_LICENSES.txt` as scoped notes about declared runtime requirements and direct build/development tools; they no longer present a complete SBOM or license-compliance certification. +- Updated all six README files and `SECURITY.md` to describe local storage, loopback binding, inherited process permissions, maintainer response targets, and the limits of the available evidence. +- Replaced comparative claims about other products' network behavior, process permissions, and security response with “not assessed” entries. +- Removed dated test-count, zero-egress, RunAsInvoker, and response-SLA badges; the existing CI badge remains the live status indicator. +- Revised the § 521 BGB note to leave application and consequences to the specific circumstances; the repository license remains unchanged. +- Revised `CONTRIBUTING.md` with a local checkout workflow and reproducible editable-install, test, lint, and build commands in English and German. +- Updated `llms.txt` with a 2026-10-12 review date and current implementation boundaries. +- Added a dated editorial supersession notice to `MARKETING-LOG.txt`; prior marketing text remains as historical material. +- Reworked `RELEASE_GATE.md` to keep version 1.0.5 frozen, distinguish the historical 1.0.1 record, and state that the current release gate is not cleared. +- Kept useful metadata, version, navigation, anchor, asset, runtime-import, CI, contributor-command, and host-sync tests; removed literal tests of old marketing, legal, and security claims. +- Preserved package version 1.0.5 and made no release or upload. ## [1.0.5] - 2026-10-04 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b933a0b..957d1fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,63 +7,82 @@ ## English -Thank you for contributing to `llm-note`. We follow strict standards for local-first architecture, privacy guarantees, and software quality. +Thank you for contributing to `llm-note`. We aim to keep the local-first architecture, public documentation, and software quality accurate and consistent. -### 1. Architectural Mandates & Invariants -- **100% Local-First & Zero Egress**: Never introduce network calls, remote analytics, or telemetry. -- **Zero External Runtime Dependencies**: Runtime code must strictly rely only on Python's standard library and SQLite. Build tools (`hatchling`, `pytest`, `ruff`) remain dev-only. -- **Unprivileged Execution (`RunAsInvoker`)**: Never require administrative or root privileges. -- **System Invariants**: Respect `INV-LOCAL-01` through `INV-SLA-10` defined in `THIRD_PARTY_LICENSES.md`. +### 1. Architecture and documentation -### 2. Plan D Local Development Workflow -- Development takes place in canonical Git clone (`C:\_Local_DEV\repos\llm-note`). -- OneDrive locations serve purely as gitless projections/mirrors for multi-device visibility. -- Never initialize `.git` inside cloud synchronization directories. +- **Local-first core:** Do not introduce external telemetry or cloud clients into core runtime code. This is a development rule; it is not a claim that the operating system blocks all network egress. +- **Runtime dependencies:** The project currently declares no additional Python runtime packages and uses the Python standard library and SQLite. Build and development tools are separate from runtime dependencies. +- **Process permissions:** Do not require administrative or root elevation. The process inherits the permissions of the process that launches it; this statement is not a Windows execution certification. +- Keep security, privacy, and dependency statements tied to checked source or distribution evidence. Do not present tests or documentation strings as a security or compliance certification. + +### 2. Local development workflow + +- Work from a local Git checkout at the repository root. +- OneDrive locations may serve as gitless projections or mirrors for multi-device visibility. +- Do not initialize a Git repository inside a cloud-synchronization directory. + +### 3. Version freeze discipline (T-20260920-167562623) -### 3. Version Freeze Discipline (T-20260920-167562623) - Package versions are frozen unless an explicit version release ticket is assigned. -- All technical hygiene improvements, contract tests, and non-breaking refinements are documented under `## [Unreleased]` in `CHANGELOG.md`. +- Technical hygiene improvements, contract tests, and non-breaking refinements belong under `## [Unreleased]` in `CHANGELOG.md`. + +### 4. Quality gates and local verification + +Before opening a pull request, run the project verification suite: -### 4. Quality Gates & Local Verification -Before opening a pull request, run the complete verification suite: ```bash -# Editable install -pip install -e . +# Editable install and local verification tools +python -m pip install -e . pytest ruff build -# Testing & Linting +# Tests and lint python -m pytest -ra -v ruff check llm_note tests -# Bytecode compilation & build check +# Bytecode compilation and local build check python -m compileall -q . python -m build git diff --check ``` +These commands validate the local checkout; they do not publish a release. + --- ## Deutsch -Vielen Dank für dein Interesse an `llm-note`. Wir verfolgen kompromisslose Standards für Offline-Autarkie, Datenschutz und Softwarequalität. +Vielen Dank für deinen Beitrag zu `llm-note`. Wir halten die lokal ausgerichtete Architektur, die öffentliche Dokumentation und die Qualitätsangaben sachlich und aufeinander abgestimmt. + +### 1. Architektur und Dokumentation -### 1. Architektur-Vorgaben & Invarianten -- **100% Lokal-Zuerst & Zero Egress**: Keine externen Netzwerkaufrufe, keine Telemetrie, kein Tracking. -- **Null externe Laufzeit-Abhängigkeiten**: Der Produktionscode nutzt ausschließlich die Python-Standardbibliothek und SQLite. -- **Unprivilegierte Ausführung (`RunAsInvoker`)**: Keinerlei Admin- oder Root-Rechte erforderlich. -- **System-Invarianten**: Einhaltung von `INV-LOCAL-01` bis `INV-SLA-10` gemäß `THIRD_PARTY_LICENSES.md`. +- **Lokaler Kern:** Führe keine externen Telemetrie- oder Cloud-Clients in den Laufzeitkern ein. Das ist eine Entwicklungsregel und keine Aussage, dass das Betriebssystem jeden Netzwerkverkehr blockiert. +- **Laufzeitabhängigkeiten:** Das Projekt deklariert derzeit keine zusätzlichen Python-Laufzeitpakete und verwendet die Python-Standardbibliothek sowie SQLite. Build- und Entwicklungswerkzeuge sind davon getrennt. +- **Prozessrechte:** Fordere keine Administrator- oder Root-Erhöhung an. Der Prozess übernimmt die Berechtigungen des aufrufenden Prozesses; das ist keine Windows-Ausführungszertifizierung. +- Sicherheits-, Datenschutz- und Abhängigkeitsaussagen müssen sich auf geprüften Quellcode oder konkrete Distributionsbelege stützen. Tests und Dokumentationstexte sind keine Sicherheits- oder Compliance-Zertifizierung. -### 2. Plan-D-Entwicklungsworkflow -- Kanonischer Arbeitsort ist der lokale Git-Klon (`C:\_Local_DEV\repos\llm-note`). -- OneDrive ist lediglich ein gitloser Projektionsspiegel zur geräteübergreifenden Verfügbarkeit. +### 2. Lokaler Entwicklungsworkflow + +- Entwickle in einem lokalen Git-Klon im Repository-Stammverzeichnis. +- OneDrive-Pfade können gitlose Projektionen oder Spiegel für die Verfügbarkeit auf mehreren Geräten sein. +- Initialisiere kein Git-Repository in einem Cloud-Synchronisationsordner. ### 3. Versions-Einfrier-Disziplin (T-20260920-167562623) -- Versionen bleiben stabil eingefroren; Neuerungen werden unter `## [Unreleased]` in `CHANGELOG.md` eingetragen. -### 4. Quality Gates +- Paketversionen bleiben eingefroren, sofern kein ausdrückliches Versionierungs-Ticket vorliegt. +- Technische Pflege, Vertragstests und nicht rückwärtsbrechende Verbesserungen gehören unter `## [Unreleased]` in `CHANGELOG.md`. + +### 4. Qualitätsprüfungen und lokale Verifikation + +Führe vor einem Pull Request die Projektprüfungen aus: + ```bash +python -m pip install -e . pytest ruff build python -m pytest -ra -v ruff check llm_note tests python -m compileall -q . +python -m build git diff --check ``` + +Diese Befehle prüfen den lokalen Klon; sie veröffentlichen kein Release. diff --git a/MARKETING-LOG.txt b/MARKETING-LOG.txt index 1ca85a3..09266a4 100644 --- a/MARKETING-LOG.txt +++ b/MARKETING-LOG.txt @@ -1,3 +1,30 @@ +=============================================================================== +EDITORIAL SUPERSESSION — 2026-10-12 +=============================================================================== + +The material below is retained as historical marketing and discoverability +planning. It is not a current security, legal, licensing, or service-level +certification. + +The following historical claims are superseded: zero-egress or air-gapped +operation; no network access under every environment; a complete SBOM or +zero-copyleft certification; RunAsInvoker certification; guaranteed response +or fix deadlines; and categorical conclusions about § 521 BGB. + +Current bounded product facts: the project declares no additional Python +runtime packages; core notes are stored in local SQLite and plain-text files; +the optional web interface binds to loopback; and the process inherits the +launching process's permissions. The application does not provide an +operating-system egress block, sandbox, or privilege drop. SECURITY.md describes +maintainer response targets, not guaranteed deadlines. The repository license +is MIT (see LICENSE); dependency notes do not certify complete transitive +license status. Legal applicability depends on the facts and is not determined +by this marketing log. + +The comparative table and search phrases below are retained for history and +should not be treated as verified statements about other products or as +current guarantees about llm-note. + =============================================================================== llm-note MARKETING & DISCOVERABILITY LOG =============================================================================== diff --git a/README.md b/README.md index 8e488f4..f0bf2b5 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,8 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Platform: Windows | Linux | macOS](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 34 Passed](https://img.shields.io/badge/Tests-34%20Passed%20%7C%20100%25-brightgreen.svg)](tests/) -[![Verified: 2026-10-11](https://img.shields.io/badge/Verified-2026--10--11-blue.svg)](CHANGELOG.md) +[![Docs updated: 2026-10-12](https://img.shields.io/badge/Docs-updated-2026--10--12-blue.svg)](CHANGELOG.md) [![Contributing: Guide](https://img.shields.io/badge/Contributing-Guide-blue.svg)](CONTRIBUTING.md) -[![Privacy: 100% Local First](https://img.shields.io/badge/Privacy-100%25%20Local--First-success.svg)](SECURITY.md) -[![Network: Zero Egress](https://img.shields.io/badge/Network-Zero%20Egress-blue.svg)](SECURITY.md) -[![Security: RunAsInvoker](https://img.shields.io/badge/Security-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Response](https://img.shields.io/badge/SLA-48h%20Response-blueviolet.svg)](SECURITY.md) [![Dependencies: 0 Stdlib Only](https://img.shields.io/badge/Dependencies-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code Style: Ruff](https://img.shields.io/badge/Code%20Style-Ruff-000000.svg)](https://github.com/astral-sh/ruff) [![Ecosystem: doc-bricks](https://img.shields.io/badge/Ecosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) @@ -23,7 +18,7 @@ [English](README.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [简体中文](README_zh-Hans.md) · [日本語](README_ja.md) · [Русский](README_ru.md) > [!NOTE] -> **Privacy-First & Local-Only**: `llm-note` operates entirely on local SQLite and plain-text files. It requires zero API keys, no cloud servers, no vector database overhead, and makes no outbound network requests. Ideal for secure, air-gapped, and privacy-conscious AI agent workflows. +> **Local-first note storage:** `llm-note` stores notes in local SQLite and plain-text files. Core note storage does not require a hosted notes service or API key. The optional web interface binds to loopback; host settings govern network access. --- @@ -35,17 +30,17 @@ 4. [Note & Transfer Lifecycle Sequence](#4-note--transfer-lifecycle-sequence) 5. [Target Personas & Discoverability](#5-target-personas--discoverability) 6. [Comparative Matrix vs. Alternatives](#6-comparative-matrix-vs-alternatives) -7. [Governance & Runtime Invariants](#7-governance--runtime-invariants) +7. [Governance & Implementation Notes](#7-governance--runtime-invariants) 8. [Denkarium Local Web GUI Guide](#8-denkarium-local-web-gui-guide) 9. [CLI Complete Reference & Examples](#9-cli-complete-reference--examples) 10. [Python API Guide & Code Examples](#10-python-api-guide--code-examples) 11. [Agent Skill & Workflow Integration](#11-agent-skill--workflow-integration) 12. [File-Based Inboxes & Transfer Semantics](#12-file-based-inboxes--transfer-semantics) 13. [Sibling Ecosystem Matrix](#13-sibling-ecosystem-matrix) -14. [Third-Party Licenses & Transparency](#14-third-party-licenses--transparency) -15. [Security Policy & SLAs](#15-security-policy--slas) +14. [Third-Party Dependencies & License Scope](#14-third-party-licenses--transparency) +15. [Security Policy & Response Targets](#15-security-policy--slas) 16. [Verification & Contract Test Suite](#16-verification--contract-test-suite) -17. [German Statutory Notice (§ 521 BGB)](#17-german-statutory-notice--521-bgb) +17. [Legal Note: § 521 BGB](#17-german-statutory-notice--521-bgb) 18. [Roadmap & Changelog](#18-roadmap--changelog) --- @@ -70,8 +65,8 @@ AI assistants and LLM agents frequently need a place to record decisions, captur `llm-note` provides the ideal architectural middle ground: - **Zero External Runtime Dependencies**: Built entirely upon the Python standard library (`sqlite3`, `http.server`, `urllib`, `argparse`, `json`, `pathlib`). -- **Dual-Store Flexibility**: Combines structured SQLite thought entries (`data/notes.db`) with human-editable plain-text inboxes (`notebooks/*.txt`). -- **BACH Extraction Provenance**: Cleanly decoupled from the BACH desktop assistant codebase (specifically Notizblock and Denkarium) and open-sourced under the permissive MIT license. +- **Dual-Store Flexibility**: Combines structured SQLite thought entries (CLI default: `llm-note.db`; path configurable) with human-editable plain-text inboxes (`notebooks/*.txt`). +- **BACH Extraction Provenance**: Cleanly decoupled from the [BACH desktop assistant codebase](https://github.com/ellmos-ai/bach), specifically Notizblock and Denkarium, and open-sourced under the permissive MIT license. --- @@ -85,7 +80,7 @@ AI assistants and LLM agents frequently need a place to record decisions, captur - **Plain-Text Notebook Inboxes (`FileNotebookStore`)**: Manage portable plain-text notes with `#NB:` categorization markers and atomic cross-process file locking. - **Embedded Denkarium Web UI**: Zero-install loopback browser interface bound strictly to `127.0.0.1` using standard library `http.server` and system fonts. - **Multi-Locale Translation**: Native message localization across 6 languages: English, German, Spanish, Simplified Chinese, Japanese, and Russian. -- **Turnkey Agent Skill**: Bundled `skills/llm-note/SKILL.md` ready for immediate discovery and invocation by autonomous agents. +- **Agent Skill Source**: The source repository contains `skills/llm-note/SKILL.md`; `pyproject.toml` packages only `llm_note`, so the wheel does not include that source path. - **Deterministic Search**: Literal substring searches without wildcard surprises, with strict query limits (`0` to `1000`). --- @@ -113,7 +108,7 @@ graph TD end subgraph LocalStorage["Local Storage Layer"] - DB[("data/notes.db
(SQLite Thought Log)")] + DB[("llm-note.db
(SQLite Thought Log; CLI default)")] Notebooks["notebooks/*.txt
(Plain-Text Inboxes)"] LockFile[".llm-note.lock (Atomic Coordination)"] end @@ -182,7 +177,7 @@ sequenceDiagram | Persona ID | Target Persona | Core Need | Key Value Provided | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **Autonomous Agent Builders** | Lightweight thought memory across LLM context resets | Zero-dependency SQLite store with instant embeddability | -| `[PERSONA-02]` | **Privacy-Conscious Developers** | Air-gapped, zero-egress note taking and inboxes | 100% local operation with zero telemetry or network calls | +| `[PERSONA-02]` | **Privacy-Conscious Developers** | Local SQLite notes and text inboxes without a hosted notes service | Local-first storage; host policy controls network access | | `[PERSONA-03]` | **Desktop AI Assistant Users** | Instant visual thought browser without Node/Electron | Built-in loopback Denkarium GUI (`127.0.0.1`) | | `[PERSONA-04]` | **Open-Science Researchers** | Git-trackable, auditable thought and experiment logs | Plain-text inboxes and standard SQLite single-file databases | @@ -203,14 +198,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. Storage Engine** | **SQLite + TXT** | Markdown files | SQLite / Sync | Vector embeddings | Single SQLite file | | **2. Runtime Dependencies** | **0 (Stdlib only)** | Electron / Node | Electron / DB | Heavy C++ / Py | 0 (C binary) | -| **3. Network Egress** | **Zero / Air-Gapped** | Plugins may leak | Sync service | Remote / Cloud API | Zero / Local | +| **3. Network requirements** | **Local storage; host policy applies** | Not assessed | Not assessed | Not assessed | Not assessed | | **4. Agent Python API** | **First-Class Native** | Community REST | Community API | Complex client | Raw SQL required | | **5. Embedded Web GUI** | **Built-in (127.0.0.1)** | Desktop App | Desktop App | Separate SaaS | None | | **6. Plain-Text Inbox Sync** | **Built-in (`#NB:`)** | Manual folders | Manual imports | N/A | Manual scripts | | **7. Multi-Locale Engine** | **6 Bundled Locales** | Community pack | Community pack | English-centric | English only | -| **8. Execution Privilege** | **RunAsInvoker** | User / Desktop | User / Desktop | Docker / Cloud | User | -| **9. Agent Skill Packaging** | **Bundled SKILL.md** | Third-party | Third-party | Custom code | None | -| **10. Security Response SLA** | **48h / 5d Formal** | Community | Community | Enterprise-only | Public domain | +| **8. Process permissions** | **Inherits caller permissions** | Not assessed | Not assessed | Not assessed | Not assessed | +| **9. Agent Skill Source** | **Source repository; not in wheel** | Third-party | Third-party | Custom code | None | +| **10. Security response information** | **Maintainer targets in SECURITY.md** | Not assessed | Not assessed | Not assessed | Not assessed | --- @@ -218,20 +213,20 @@ sequenceDiagram -## 7. Governance & Runtime Invariants +## 7. Governance & Implementation Notes -The `llm-note` engine operates under ten immutable architectural invariants: +The items below describe current implementation characteristics based on source. They are not immutable guarantees or an external security certification: -- `INV-LOCAL-01`: **100% Local-First & Zero Egress** — No outbound network requests, no telemetry, no cloud sync. -- `INV-LOCAL-02`: **SQLite Single-File Storage** — Structured ACID database (`data/notes.db`) with deterministic table layouts. +- `INV-LOCAL-01`: **Local-first storage** — Notes are stored in local SQLite and plain-text files; this does not block network access at the host level. +- `INV-LOCAL-02`: **SQLite Single-File Storage** — Structured ACID database; the CLI default file is `llm-note.db` and the path is configurable. - `INV-LOCAL-03`: **Plain-Text Notebook Inboxes** — Human-readable text inboxes (`notebooks/*.txt`) with `#NB:` categorization. - `INV-LOCAL-04`: **Standard Library Only** — Zero third-party runtime dependencies; runs on any standard Python 3.10+ runtime. - `INV-LOCAL-05`: **Crash-Safe Atomic Transfers** — Cross-process locking via `.llm-note.lock` and `#LLM-NOTE-ID` idempotency markers. - `INV-LOCAL-06`: **Loopback-Bound Web GUI** — Denkarium strictly listens on `127.0.0.1`; supports `--no-browser`. - `INV-LOCAL-07`: **Multi-Locale I18N** — 6 bundled localization catalogs: EN, DE, ES, ZH, JA, RU. -- `INV-LOCAL-08`: **RunAsInvoker Non-Elevation** — Operates entirely in unprivileged user space; zero administrative elevation. -- `INV-LOCAL-09`: **Agent Skill Packaging** — Ships a complete agent skill (`skills/llm-note/SKILL.md`) for LLM workflows. -- `INV-LOCAL-10`: **48-Hour Security SLA** — Formal vulnerability response commitments governed by `SECURITY.md`. +- `INV-LOCAL-08`: **Process permissions** — The application does not request elevation and inherits the permissions of the process that launches it. +- `INV-LOCAL-09`: **Agent skill source** — The source repository contains [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md); `pyproject.toml` packages only `llm_note`, so the wheel does not include that source path. +- `INV-LOCAL-10`: **Maintainer response targets** — See `SECURITY.md`; acknowledgement and triage targets are not an SLA or a fix deadline. --- @@ -241,7 +236,7 @@ The `llm-note` engine operates under ten immutable architectural invariants: ## 8. Denkarium Local Web GUI Guide -The Denkarium GUI provides an instant, zero-install visual thought dashboard: +The Denkarium GUI provides an instant, zero-install visual thought dashboard. Choose one of the six languages from the Language menu. The choice is per browser and is saved in that browser’s local storage. When starting the GUI with an explicit `--locale`, that value takes priority for the initial language; otherwise, it uses the saved browser choice and falls back to English. ```bash # Launch Denkarium with default settings (opens http://127.0.0.1:8000/) @@ -284,7 +279,7 @@ This provides the `llm-note` command and the `llm_note` Python package. ```bash # Write a note with category and mood -llm-note write "Refactor caching layer" --cat dev --mood focused +llm-note write "Refactor caching layer" --cat dev --mood 4 # Read recent notes (default limit 10) llm-note read --limit 5 @@ -320,7 +315,7 @@ notes = NoteStore("data/notes.db") entry = notes.write( content="Implement deterministic seed for test suite", category="testing", - mood="neutral" + mood=4 ) print(f"Created entry #{entry.id} at {entry.created_at}") @@ -347,7 +342,7 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 11. Agent Skill & Workflow Integration -`llm-note` includes an agent skill definition at [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Autonomous agents (such as Claude Code, Antigravity, or Codex) can invoke `llm-note` directly to record persistent observations, maintain scratchpads across subagent delegations, and retain audit logs. +The source repository contains an agent skill definition at [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). The wheel packages only `llm_note` as declared in [`pyproject.toml`](pyproject.toml), so the source-only skill path is not claimed as wheel content. Autonomous agents (such as Claude Code, Antigravity, or Codex) can invoke `llm-note` to record observations and maintain scratchpads. ```markdown # Agent Tool Invocation Example @@ -376,16 +371,16 @@ To save an interim research observation: ## 13. Sibling Ecosystem Matrix -`llm-note` is part of the `doc-bricks` family under the `open-bricks` open-source umbrella: +The repositories below are related projects in the wider ecosystem; listing them does not imply direct integration with llm-note: | Project | Focus & Role in Ecosystem | Link | | :--- | :--- | :--- | | **doc-bricks/llm-note** | Local-first thought and notebook core for agents | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | Multimodal asset analysis, OCR & document transcription | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | Deterministic email parsing and compliant archiving pipeline | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | Personal video and music library with smart playlists and streaming history | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | Windows tray app for launching the local Universal Mail tools | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | Robust, cross-platform directory synchronization | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| Conflict resolution and lock manager for cloud folders | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | Umbrella catalog and foundational open developer tooling | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | Delays file operations in cloud-sync folders and verifies copy/delete fallbacks with SHA-256 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks organization profile** | GitHub organization profile and umbrella catalog; not a specific repository | [open-bricks on GitHub](https://github.com/open-bricks) | --- @@ -393,13 +388,13 @@ To save an interim research observation: -## 14. Third-Party Licenses & Transparency +## 14. Third-Party Dependencies & License Scope -`llm-note` has **0 external runtime dependencies**. All core operations rely exclusively on the Python standard library under the [Python Software Foundation License](https://docs.python.org/3/license.html). +`llm-note` declares no additional Python runtime package dependencies in `pyproject.toml`. Its core uses the Python standard library and SQLite supplied by the Python environment. -- Complete SBOM and license transparency audit: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- Zero-Copyleft verification: 100% free of GPL, AGPL, LGPL, and SSPL code. -- Unprivileged execution: Certified for `RunAsInvoker` user space. +- Scoped notes on direct declared dependencies: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) and [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt). They are not complete SBOMs. +- The dependency notes do not certify the license status of complete transitive build or development dependency trees. +- The process does not request administrative elevation and inherits the launching process permissions; this is not a platform certification. --- @@ -407,13 +402,13 @@ To save an interim research observation: -## 15. Security Policy & SLAs +## 15. Security Policy & Response Targets -We maintain a rigorous, formal vulnerability management process documented in [`SECURITY.md`](SECURITY.md): +The reporting route and maintainer response targets are documented in [`SECURITY.md`](SECURITY.md): -- **Zero Egress Contract**: The software makes zero network calls. Any unauthorized egress is classified as a critical defect. -- **48-Hour Response SLA**: Initial triage within 48 hours; resolution plan within 5 business days. -- **Contact**: Report potential security issues confidentially to `security@lukasgeiger.com`. +- **Implementation boundary:** Core notes use local storage and the optional web interface binds to loopback. The application does not block host network access or sandbox the process. +- **Maintainer response targets:** Acknowledgement within 48 hours and initial triage within 5 business days are targets, not an SLA or a promised fix deadline. +- **Contact**: Submit confidential reports through the private reporting method described in [SECURITY.md](SECURITY.md). --- @@ -442,11 +437,11 @@ python -m compileall -q . -## 17. German Statutory Notice (§ 521 BGB) +## 17. Legal Note: § 521 BGB -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. +Dieser Hinweis trifft keine Aussage dazu, ob § 521 BGB auf eine konkrete Bereitstellung anwendbar ist oder welche Haftungsfolgen eintreten. Das hängt von den Umständen des Einzelfalls ab. -This open-source software is provided free of charge under the MIT License. In accordance with § 521 of the German Civil Code (BGB), statutory liability for gratuitous provisions is limited to intent and gross negligence. +Section 521 of the German Civil Code may be relevant depending on the specific facts. This note does not determine whether it applies to a particular distribution or what liability consequences follow. --- diff --git a/README_de.md b/README_de.md index 6e19246..3ede57f 100644 --- a/README_de.md +++ b/README_de.md @@ -7,23 +7,18 @@ [![Lizenz: MIT](https://img.shields.io/badge/Lizenz-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Plattform: Windows | Linux | macOS](https://img.shields.io/badge/Plattform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 34 Bestanden](https://img.shields.io/badge/Tests-34%20Bestanden%20%7C%20100%25-brightgreen.svg)](tests/) -[![Geprüft: 2026-10-11](https://img.shields.io/badge/Gepr%C3%BCft-2026--10--11-blue.svg)](CHANGELOG.md) +[![Dokumentation aktualisiert: 2026-10-12](https://img.shields.io/badge/Dokumentation-aktualisiert-2026--10--12-blue.svg)](CHANGELOG.md) [![Mitwirken: Leitfaden](https://img.shields.io/badge/Mitwirken-Leitfaden-blue.svg)](CONTRIBUTING.md) -[![Datenschutz: 100% Lokal-Zuerst](https://img.shields.io/badge/Datenschutz-100%25%20Lokal--Zuerst-success.svg)](SECURITY.md) -[![Netzwerk: Zero Egress](https://img.shields.io/badge/Netzwerk-Zero%20Egress-blue.svg)](SECURITY.md) -[![Sicherheit: RunAsInvoker](https://img.shields.io/badge/Sicherheit-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Antwort](https://img.shields.io/badge/SLA-48h%20Antwort-blueviolet.svg)](SECURITY.md) -[![Abhaengigkeiten: 0 Stdlib Only](https://img.shields.io/badge/Abh%C3%A4ngigkeiten-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) +[![Abhängigkeiten: 0 Stdlib Only](https://img.shields.io/badge/Abh%C3%A4ngigkeiten-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code-Stil: Ruff](https://img.shields.io/badge/Code--Stil-Ruff-000000.svg)](https://github.com/astral-sh/ruff) -[![Oekosystem: doc-bricks](https://img.shields.io/badge/%C3%96kosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) +[![Ökosystem: doc-bricks](https://img.shields.io/badge/%C3%96kosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) [![Dachorganisation: open-bricks](https://img.shields.io/badge/Dachorganisation-open--bricks-blueviolet.svg)](https://github.com/open-bricks) [![LLM Bereit: llms.txt](https://img.shields.io/badge/LLM%20Bereit-llms.txt-teal.svg)](llms.txt) [Deutsch](README_de.md) · [English](README.md) · [Español](README_es.md) · [简体中文](README_zh-Hans.md) · [日本語](README_ja.md) · [Русский](README_ru.md) > [!NOTE] -> **Datenschutz & Lokal-Zuerst**: `llm-note` arbeitet vollständig auf lokalen SQLite-Datenbanken und einfachen Textdateien. Es benötigt keine API-Schlüssel, keine Cloud-Server, keinen Vektordatenbank-Overhead und stellt keine ausgehenden Netzwerkverbindungen her. Ideal für datenschutzkonforme, autarke KI-Agenten-Workflows. +> **Lokal ausgerichtete Notizen:** `llm-note` speichert Notizen lokal in SQLite und Klartextdateien. Für die Kernspeicherung ist kein gehosteter Notizdienst und kein API-Schlüssel erforderlich. Die optionale Weboberfläche bindet an Loopback; die Hostumgebung bestimmt den Netzwerkzugriff. --- @@ -35,17 +30,17 @@ 4. [Sequenzdiagramm: Notiz- & Transfer-Lebenszyklus](#4-sequenzdiagramm-notiz--und-transfer-lebenszyklus) 5. [Zielgruppen & High-Intent Suchbegriffe](#5-zielgruppen--suchbegriffe) 6. [Vergleichsmatrix gegenüber Alternativen](#6-vergleichsmatrix-gegenueber-alternativen) -7. [Governance & Laufzeit-Invarianten](#7-governance--laufzeit-invarianten) +7. [Governance & Implementierungshinweise](#7-governance--laufzeit-invarianten) 8. [Lokale Denkarium-Weboberfläche](#8-lokale-denkarium-weboberflaeche) 9. [CLI-Befehlsreferenz & Praxisbeispiele](#9-cli-befehlsreferenz--beispiele) 10. [Python API & Programmierbeispiele](#10-python-api--programmierbeispiele) 11. [Agenten-Skill & Workflow-Integration](#11-agenten-skill--workflow-integration) 12. [Text-Notizbücher & Transfer-Semantik](#12-text-notizbuecher--transfer-semantik) 13. [Ökosystem-Matrix & Verwandte Module](#13-oekosystem-matrix--verwandte-module) -14. [Drittanbieter-Lizenzen & Transparenz](#14-drittanbieter-lizenzen--transparenz) -15. [Sicherheitsrichtlinie & SLAs](#15-sicherheitsrichtlinie--slas) +14. [Drittanbieter-Abhängigkeiten & Lizenzumfang](#14-drittanbieter-lizenzen--transparenz) +15. [Sicherheitsrichtlinie & Reaktionsziele](#15-sicherheitsrichtlinie--slas) 16. [Verifikation & Test-Suite](#16-verifikation--test-suite) -17. [Gesetzlicher Haftungshinweis nach § 521 BGB](#17-gesetzlicher-haftungshinweis--521-bgb) +17. [Rechtlicher Hinweis zu § 521 BGB](#17-gesetzlicher-haftungshinweis--521-bgb) 18. [Roadmap & Änderungsprotokoll](#18-roadmap--aenderungsprotokoll) --- @@ -70,8 +65,8 @@ Autonome Agenten und LLMs müssen während komplexer Arbeitsläufe fortlaufend E `llm-note` schließt diese Lücke: - **Null externe Laufzeitabhängigkeiten**: 100% reine Python-Standardbibliothek (`sqlite3`, `http.server`, `urllib`, `argparse`, `json`, `pathlib`). -- **Duale Speicherarchitektur**: Verbindet strukturierte SQLite-Gedanken (`data/notes.db`) mit flexiblen, Git-fähigen Klartext-Notizbüchern (`notebooks/*.txt`). -- **BACH-Provenienz**: Sauber entkoppelt aus den bewährten Notizblock- und Denkarium-Komponenten des BACH-Assistentensystems und unter der permissiven MIT-Lizenz freigegeben. +- **Duale Speicherarchitektur**: Verbindet strukturierte SQLite-Gedanken (CLI-Standarddatei `llm-note.db`; Pfad konfigurierbar) mit flexiblen, Git-fähigen Klartext-Notizbüchern (`notebooks/*.txt`). +- **BACH-Provenienz**: Sauber von der [BACH-Desktop-Assistenten-Codebasis](https://github.com/ellmos-ai/bach), insbesondere Notizblock und Denkarium, entkoppelt und unter der permissiven MIT-Lizenz freigegeben. --- @@ -85,7 +80,7 @@ Autonome Agenten und LLMs müssen während komplexer Arbeitsläufe fortlaufend E - **Textdatei-Notizbücher (`FileNotebookStore`)**: Portable Text-Notizbücher mit `#NB:`-Kategorisierung und atomarer prozessübergreifender Dateisperre (`.llm-note.lock`). - **Integrierte Denkarium-Weboberfläche**: Sofort einsatzbereite Loopback-Benutzeroberfläche, strikt an `127.0.0.1` gebunden via `http.server` und mit nativen Systemschriften. - **Mehrsprachige Lokalisierung**: 6 mitgelieferte Sprachkataloge: Deutsch, Englisch, Spanisch, vereinfachtes Chinesisch, Japanisch und Russisch. -- **Schlüsselfertiger Agenten-Skill**: Fertiges `skills/llm-note/SKILL.md` für die direkte Erkennung und Werkzeugnutzung durch autonome Agenten. +- **Agenten-Skill aus dem Quellrepository**: Das Quellrepository enthält `skills/llm-note/SKILL.md`; laut `pyproject.toml` paketiert das Wheel nur `llm_note`, nicht diesen Quellpfad. - **Deterministische Suche**: Exakte Teilstring-Suche ohne SQL-Wildcard-Überraschungen mit klar begrenzten Abfragemengen (`0` bis `1000`). --- @@ -113,7 +108,7 @@ graph TD end subgraph LocalStorage["Lokale Speicherebene"] - DB[("data/notes.db
(SQLite Denkarium)")] + DB[("llm-note.db
(SQLite Denkarium; CLI-Standard)")] Notebooks["notebooks/*.txt
(Text-Notizbücher)"] LockFile[".llm-note.lock (Atomare Koordination)"] end @@ -152,15 +147,15 @@ sequenceDiagram UserOrAgent ->> NoteStore: write("Architekturentscheidung", category="design") NoteStore ->> NoteStore: Datensatz mit Zeitstempel & Stimmung in SQLite anlegen - NoteStore -->> UserOrAgent: Rueckgabe Entry(id=1, category="design") + NoteStore -->> UserOrAgent: Rückgabe Entry(id=1, category="design") UserOrAgent ->> FileStore: write("Inbox-Eintrag - #NB: Projekt-Ideen") - FileStore ->> FileStore: .llm-note.lock sperren & an inbox.txt anhaengen + FileStore ->> FileStore: .llm-note.lock sperren & an inbox.txt anhängen FileStore -->> UserOrAgent: Notiz im Text-Postfach gesichert UserOrAgent ->> FileStore: transfer_marked_entries() FileStore ->> FileStore: #NB: Ziel extrahieren & stabile #LLM-NOTE-ID vergeben - FileStore ->> FileStore: Notiz atomar ins Ziel-Notizbuch ueberfuehren & Lock freigeben + FileStore ->> FileStore: Notiz atomar ins Ziel-Notizbuch überführen & Lock freigeben FileStore -->> UserOrAgent: Transfer abgeschlossen (0 Duplikatsrisiko) UserOrAgent ->> Denkarium: Loopback-GUI aufrufen (http://127.0.0.1:8000/) @@ -182,7 +177,7 @@ sequenceDiagram | Persona ID | Zielgruppe | Kernbedarf | Bereitgestellter Nutzen | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **Autonome Agenten-Entwickler** | Gedankenspeicher über Kontext-Resets hinweg | Null-Abhängigkeiten SQLite-Speicher zur sofortigen Einbettung | -| `[PERSONA-02]` | **Datenschutzbewusste Entwickler** | Vollständig autarker Notizblock ohne Netzwerkzugriff | 100% lokaler Betrieb ohne Telemetrie oder Serveraufrufe | +| `[PERSONA-02]` | **Datenschutzbewusste Entwickler** | Lokale SQLite-Notizen und Klartext-Postfächer ohne gehosteten Notizdienst | Lokal ausgerichtete Speicherung; der Host steuert den Netzwerkzugriff | | `[PERSONA-03]` | **Desktop-KI-Assistenten-Nutzer** | Schnelle visuelle Gedankenübersicht ohne Node/Electron | Integrierte Loopback Denkarium-Oberfläche (`127.0.0.1`) | | `[PERSONA-04]` | **Open-Science-Forscher** | In Git versionierbare, auditierbare Notizen & Logbücher | Text-Dateien und standardkonforme SQLite-Einzeldateien | @@ -203,14 +198,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. Speicher-Engine** | **SQLite + TXT** | Markdown-Dateien | SQLite / Sync | Vektor-Embeddings | Einzelne SQLite-Datei | | **2. Laufzeitabhängigkeiten** | **0 (Nur Stdlib)** | Electron / Node | Electron / DB | Schweres C++ / Py | 0 (C-Binary) | -| **3. Netzwerkzugriff** | **Zero / Air-Gapped** | Plugins unklar | Sync-Dienst | Remote- / Cloud-API | Zero / Lokal | +| **3. Netzwerkanforderungen** | **Lokale Speicherung; Hostrichtlinie gilt** | Nicht geprüft | Nicht geprüft | Nicht geprüft | Nicht geprüft | | **4. Agenten Python-API** | **Erstklassig Nativ** | Community REST | Community-API | Komplexe Clients | Reines SQL nötig | | **5. Lokale Web-GUI** | **Integriert (127.0.0.1)**| Desktop-App | Desktop-App | Separates SaaS | Keine | | **6. Text-Postfach Sync** | **Integriert (`#NB:`)** | Manuelle Ordner | Manueller Import | Nicht vorhanden | Manuelle Skripte | | **7. Lokalisierung** | **6 Sprachdateien** | Community-Pack | Community-Pack | Meist nur Englisch | Nur Englisch | -| **8. Privilegienstufe** | **RunAsInvoker** | Benutzer / Desktop | Benutzer / Desktop | Docker / Cloud | Benutzer | -| **9. Agenten-Skill** | **SKILL.md inklusive** | Drittanbieter | Drittanbieter | Eigener Code | Keine | -| **10. Sicherheits-SLA** | **48h / 5d Verbindlich**| Community | Community | Nur Enterprise | Public Domain | +| **8. Prozessrechte** | **Übernimmt Rechte des Aufrufers** | Nicht geprüft | Nicht geprüft | Nicht geprüft | Nicht geprüft | +| **9. Agenten-Skill-Quelle** | **Quellrepository; nicht im Wheel** | Drittanbieter | Drittanbieter | Eigener Code | Keine | +| **10. Informationen zur Sicherheitsreaktion** | **Maintainer-Ziele in SECURITY.md** | Nicht geprüft | Nicht geprüft | Nicht geprüft | Nicht geprüft | --- @@ -218,20 +213,20 @@ sequenceDiagram -## 7. Governance & Laufzeit-Invarianten +## 7. Governance & Implementierungshinweise -`llm-note` garantiert zehn unveränderliche Systeminvarianten: +Die folgenden Punkte beschreiben den aktuellen, im Quellcode belegten Stand. Sie sind keine unveränderlichen Garantien oder externe Sicherheitszertifizierung: -- `INV-LOCAL-01`: **100% Lokal-Zuerst & Zero Egress** — Keine ausgehenden Netzwerkaufrufe, keine Telemetrie, kein Cloud-Sync. -- `INV-LOCAL-02`: **SQLite-Einzeldatei-Speicher** — Strukturierte ACID-Datenbank (`data/notes.db`) mit deterministischem Schema. +- `INV-LOCAL-01`: **Lokal ausgerichtete Speicherung** — Notizen liegen in lokalem SQLite und Klartextdateien; der Host-Netzwerkzugriff wird dadurch nicht blockiert. +- `INV-LOCAL-02`: **SQLite-Einzeldatei-Speicher** — Strukturierte ACID-Datenbank; die CLI-Standarddatei heißt `llm-note.db`, der Pfad ist konfigurierbar. - `INV-LOCAL-03`: **Klartext-Notizbuch-Postfächer** — Für Menschen lesbare Textdateien (`notebooks/*.txt`) mit `#NB:`-Kategorisierung. - `INV-LOCAL-04`: **Ausschließlich Standardbibliothek** — Null externe Laufzeitabhängigkeiten; lauffähig auf jedem Standard-Python 3.10+. - `INV-LOCAL-05`: **Absturzsichere atomare Transfers** — Dateisperren via `.llm-note.lock` und `#LLM-NOTE-ID`-Idempotenz-Marker. - `INV-LOCAL-06`: **Strikte Loopback-Web-GUI** — Denkarium lauscht ausschließlich auf `127.0.0.1`; `--no-browser` Modus verfügbar. - `INV-LOCAL-07`: **Mehrsprachigkeit (I18N)** — 6 vollständige Lokalisierungskataloge: DE, EN, ES, ZH, JA, RU. -- `INV-LOCAL-08`: **RunAsInvoker Unprivilegiert** — Läuft vollständig im Benutzerraum ohne administrative Rechte (keine UAC-Elevation). -- `INV-LOCAL-09`: **Fertiges Agenten-Skill-Paket** — Liefert `skills/llm-note/SKILL.md` für sofortige Werkzeugintegration mit. -- `INV-LOCAL-10`: **48-Stunden Sicherheits-SLA** — Verbindliche Reaktionszeiten bei Sicherheitsmeldungen gemäß `SECURITY.md`. +- `INV-LOCAL-08`: **Prozessrechte** — Die Anwendung fordert keine Erhöhung an und übernimmt die Berechtigungen des aufrufenden Prozesses. +- `INV-LOCAL-09`: **Agenten-Skill-Quelle** — Das Quellrepository enthält [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md); `pyproject.toml` paketiert nur `llm_note`, daher wird dieser Quellpfad nicht als Wheel-Inhalt ausgewiesen. +- `INV-LOCAL-10`: **Reaktionsziele des Maintainers** — `SECURITY.md` nennt Eingangs- und Triageziele; sie sind kein SLA und keine Frist für eine Korrektur. --- @@ -241,16 +236,16 @@ sequenceDiagram ## 8. Lokale Denkarium-Weboberfläche -Die Denkarium-Oberfläche bietet eine sofortige, installationsfreie visuelle Notizverwaltung: +Die Denkarium-Oberfläche bietet eine sofortige, installationsfreie visuelle Notizverwaltung. Wähle im Menü „Sprache“ zwischen den sechs Sprachen. Die Auswahl gilt pro Browser und wird im lokalen Speicher dieses Browsers gesichert. Wird das GUI mit einem expliziten `--locale` gestartet, hat dieser Wert für die Anfangssprache Vorrang; andernfalls gilt die gespeicherte Browserauswahl, mit Englisch als Standard. ```bash -# Denkarium mit Standardwerten starten (oeffnet http://127.0.0.1:8000/) +# Denkarium mit Standardwerten starten (öffnet http://127.0.0.1:8000/) llm-note --locale de gui # Eigene Datenbank, Port und deutsche Sprache vorgeben llm-note --db data/notes.db --locale de gui --port 8765 -# Headless-Modus fuer Hintergrundprozesse oder Tests +# Headless-Modus für Hintergrundprozesse oder Tests llm-note gui --port 8765 --no-browser ``` @@ -284,15 +279,15 @@ Damit stehen der Befehl `llm-note` und das Python-Paket `llm_note` bereit. ```bash # Notiz mit Kategorie und Stimmung erfassen -llm-note --locale de write "Caching-Schicht optimieren" --cat dev --mood focused +llm-note --locale de write "Caching-Schicht optimieren" --cat dev --mood 4 -# Juengste Notizen lesen (Standardlimit: 10) +# Jüngste Notizen lesen (Standardlimit: 10) llm-note --locale de read --limit 5 -# Notizen woertlich suchen (keine Wildcard-Ersetzung) +# Notizen wörtlich suchen (keine Wildcard-Ersetzung) llm-note --locale de search "Caching" -# Brainstorming-Eintrag fuer spaetere Weiterverarbeitung anlegen +# Brainstorming-Eintrag für spätere Weiterverarbeitung anlegen llm-note --locale de brainstorm "Zero-Copy Serialisierungsoptionen" # Zusammenfassende Statistik abrufen @@ -318,9 +313,9 @@ notes = NoteStore("data/notes.db") # 2. Strukturierten Gedanken anlegen entry = notes.write( - content="Deterministischen Seed fuer Test-Suite einrichten", + content="Deterministischen Seed für Test-Suite einrichten", category="testing", - mood="neutral" + mood=4 ) print(f"Eintrag #{entry.id} erstellt am {entry.created_at}") @@ -329,14 +324,14 @@ matches = notes.search("deterministisch") for match in matches: print(f"Treffer: {match.content} [{match.category}]") -# 4. Notiz zur Aufgabe befoerdern +# 4. Notiz zur Aufgabe befördern notes.promote(entry.id, target="task") -# 5. Text-Notizbuecher koordinieren +# 5. Text-Notizbücher koordinieren notebooks = FileNotebookStore("notebooks") notebooks.write("Release-Mitteilung vorbereiten\n#NB: Marketing") transferred = notebooks.transfer_marked_entries() -print(f"{transferred} Eintraege in Themen-Notizbuecher uebertragen.") +print(f"{transferred} Einträge in Themen-Notizbücher übertragen.") ``` --- @@ -347,12 +342,12 @@ print(f"{transferred} Eintraege in Themen-Notizbuecher uebertragen.") ## 11. Agenten-Skill & Workflow-Integration -`llm-note` enthält eine vollständige Skill-Definition unter [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Autonome Agenten (wie Claude Code, Antigravity oder Codex) können `llm-note` direkt als Werkzeug einsetzen, um Beobachtungen festzuhalten, Notizblöcke über Subagenten-Delegationen hinweg zu teilen und Prüfprotokolle zu pflegen. +Das Quellrepository enthält die Agenten-Skill-Definition [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Das Wheel paketiert laut [`pyproject.toml`](pyproject.toml) nur `llm_note`; der Skill-Quellpfad wird daher nicht als Wheel-Inhalt behauptet. Autonome Agenten können `llm-note` nutzen, um Beobachtungen festzuhalten und Notizblöcke zu pflegen. ```markdown -# Beispiel fuer einen Agenten-Werkzeugaufruf +# Beispiel für einen Agenten-Werkzeugaufruf Zur Sicherung einer Zwischenbeobachtung: -`llm-note write "3 Randfaelle beim Token-Parsing identifiziert" --cat research` +`llm-note write "3 Randfälle beim Token-Parsing identifiziert" --cat research` ``` --- @@ -376,16 +371,16 @@ Zur Sicherung einer Zwischenbeobachtung: ## 13. Ökosystem-Matrix & Verwandte Module -`llm-note` gehört zur `doc-bricks`-Familie unter dem Dach von `open-bricks`: +Die folgenden Einträge verweisen auf verwandte Repositories im weiteren Ökosystem; ihre Nennung behauptet keine direkte Integration mit llm-note: | Projekt | Fokus & Rolle im Ökosystem | Verweis | | :--- | :--- | :--- | | **doc-bricks/llm-note** | Lokaler Notiz- und Denkarium-Kern für Agenten | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | Multimodale Analyse, OCR & Dokumenten-Transkription | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | Deterministischer E-Mail-Parser und gesetzeskonformes Archiv | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | Persönliche Video- und Musikbibliothek mit Smart-Playlists und Streaming-Verlauf | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | Windows-Infobereichs-App zum Starten der lokalen Universal-Mail-Werkzeuge | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | Plattformübergreifende Verzeichnis-Synchronisation | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| Sperren- und Konfliktlöser für Cloud-Ordner | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | Dachkatalog für souveräne Entwicklerwerkzeuge | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | Verzögert Dateiaktionen in Cloud-Sync-Ordnern und prüft Kopier-/Lösch-Fallbacks mit SHA-256 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks-Organisationsprofil** | Organisationsprofil und Dachkatalog; kein einzelnes Repository | [open-bricks auf GitHub](https://github.com/open-bricks) | --- @@ -393,13 +388,13 @@ Zur Sicherung einer Zwischenbeobachtung: -## 14. Drittanbieter-Lizenzen & Transparenz +## 14. Drittanbieter-Abhängigkeiten & Lizenzumfang -`llm-note` hat **0 externe Laufzeitabhängigkeiten**. Alle Basisfunktionen nutzen ausschließlich Module der Python-Standardbibliothek unter der [Python Software Foundation License](https://docs.python.org/3/license.html). +`pyproject.toml` deklariert keine zusätzlichen Python-Laufzeitpakete. Der Kern verwendet die Python-Standardbibliothek und SQLite aus der Python-Umgebung. -- Vollständige SBOM und Lizenz-Transparenzprüfung: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- Zero-Copyleft-Zertifizierung: 100% frei von GPL, AGPL, LGPL und SSPL. -- Unprivilegierte Ausführung: Vollständig für den `RunAsInvoker`-Benutzerraum zertifiziert. +- Begrenzte Hinweise zu direkt deklarierten Abhängigkeiten: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) und [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt). Sie sind keine vollständigen SBOMs. +- Die Abhängigkeitsnotizen zertifizieren nicht den Lizenzstatus vollständiger transitiver Build- oder Entwicklungsabhängigkeiten. +- Der Prozess fordert keine Administratorerhöhung an und übernimmt die Berechtigungen des aufrufenden Prozesses; das ist keine Plattformzertifizierung. --- @@ -407,13 +402,13 @@ Zur Sicherung einer Zwischenbeobachtung: -## 15. Sicherheitsrichtlinie & SLAs +## 15. Sicherheitsrichtlinie & Reaktionsziele -Wir pflegen ein formales Verfahren zur Schwachstellenbehandlung gemäß [`SECURITY.md`](SECURITY.md): +Meldeweg und Reaktionsziele des Maintainers stehen in [`SECURITY.md`](SECURITY.md): -- **Zero Egress Vertrag**: Die Software tätigt keinerlei Netzwerkverbindungen nach außen. Unerlaubter Datenabfluss gilt als schwerer Fehler. -- **48-Stunden Reaktions-SLA**: Erste Sichtung innerhalb von 48 Stunden; Maßnahmenplan innerhalb von 5 Werktagen. -- **Kontakt**: Sicherheitsrelevante Hinweise vertraulich an `security@lukasgeiger.com` richten. +- **Implementierungsgrenze:** Der Notizkern nutzt lokale Speicherung, und die optionale Weboberfläche bindet an Loopback. Die Anwendung blockiert weder den Host-Netzwerkzugriff noch stellt sie eine Sandbox bereit. +- **Reaktionsziele des Maintainers:** Eingangsbestätigung innerhalb von 48 Stunden und Beginn der Triage innerhalb von 5 Werktagen sind Ziele, kein SLA und keine zugesagte Korrekturfrist. +- **Kontakt**: Vertrauliche Sicherheitsmeldungen bitte über den in [SECURITY.md](SECURITY.md) beschriebenen privaten Meldeweg einreichen. --- @@ -429,10 +424,10 @@ Die Testsuite lässt sich lokal wie folgt ausführen: # Modultests und Vertragstests starten python -m pytest -ra -v -# Schnellen Ruff-Linter ausfuehren +# Schnellen Ruff-Linter ausführen ruff check . -# Bytecode-Kompilierung pruefen +# Bytecode-Kompilierung prüfen python -m compileall -q . ``` @@ -442,11 +437,11 @@ python -m compileall -q . -## 17. Gesetzlicher Haftungshinweis nach § 521 BGB +## 17. Rechtlicher Hinweis zu § 521 BGB -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. +Dieser Hinweis trifft keine Aussage dazu, ob § 521 BGB auf eine konkrete Bereitstellung anwendbar ist oder welche Haftungsfolgen eintreten. Das hängt von den Umständen des Einzelfalls ab. -This open-source software is provided free of charge under the MIT License. In accordance with § 521 of the German Civil Code (BGB), statutory liability for gratuitous provisions is limited to intent and gross negligence. +§ 521 BGB kann abhängig von den konkreten Umständen relevant sein. Dieser Hinweis bestimmt weder die Anwendbarkeit auf eine bestimmte Bereitstellung noch deren Haftungsfolgen. --- diff --git a/README_es.md b/README_es.md index a7422c2..4ce5040 100644 --- a/README_es.md +++ b/README_es.md @@ -7,11 +7,6 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Platform: Windows | Linux | macOS](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 30 Passed](https://img.shields.io/badge/Tests-30%20Passed%20%7C%20100%25-brightgreen.svg)](tests/) -[![Privacy: 100% Local First](https://img.shields.io/badge/Privacy-100%25%20Local--First-success.svg)](SECURITY.md) -[![Network: Zero Egress](https://img.shields.io/badge/Network-Zero%20Egress-blue.svg)](SECURITY.md) -[![Security: RunAsInvoker](https://img.shields.io/badge/Security-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Response](https://img.shields.io/badge/SLA-48h%20Response-blueviolet.svg)](SECURITY.md) [![Dependencies: 0 Stdlib Only](https://img.shields.io/badge/Dependencies-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code Style: Ruff](https://img.shields.io/badge/Code%20Style-Ruff-000000.svg)](https://github.com/astral-sh/ruff) [![Ecosystem: doc-bricks](https://img.shields.io/badge/Ecosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) @@ -22,7 +17,7 @@ *Traducción asistida por máquina; el README en inglés es la versión de referencia.* > [!NOTE] -> **Privacidad primero y solo local**: `llm-note` funciona íntegramente con SQLite local y archivos de texto plano. No requiere claves de API, ni servidores en la nube, ni la sobrecarga de una base de datos vectorial, y no realiza ninguna solicitud de red saliente. Ideal para flujos de trabajo de agentes de IA seguros, aislados de la red (air-gapped) y atentos a la privacidad. +> **Almacenamiento local de notas:** `llm-note` guarda las notas en SQLite local y archivos de texto plano. El almacenamiento principal no necesita un servicio de notas alojado ni una clave API. La interfaz web opcional se vincula a loopback; la configuración del host determina el acceso a la red. --- @@ -34,17 +29,17 @@ 4. [Secuencia del ciclo de vida de notas y transferencias](#4-note--transfer-lifecycle-sequence) 5. [Personas objetivo y descubribilidad](#5-target-personas--discoverability) 6. [Matriz comparativa frente a alternativas](#6-comparative-matrix-vs-alternatives) -7. [Gobernanza e invariantes de ejecución](#7-governance--runtime-invariants) +7. [Gobernanza y notas de implementación](#7-governance--runtime-invariants) 8. [Guía de la interfaz web local Denkarium](#8-denkarium-local-web-gui-guide) 9. [Referencia completa de la CLI y ejemplos](#9-cli-complete-reference--examples) 10. [Guía de la API de Python y ejemplos de código](#10-python-api-guide--code-examples) 11. [Skill de agente e integración en flujos de trabajo](#11-agent-skill--workflow-integration) 12. [Bandejas de entrada basadas en archivos y semántica de transferencia](#12-file-based-inboxes--transfer-semantics) 13. [Matriz del ecosistema hermano](#13-sibling-ecosystem-matrix) -14. [Licencias de terceros y transparencia](#14-third-party-licenses--transparency) -15. [Política de seguridad y SLA](#15-security-policy--slas) +14. [Dependencias de terceros y alcance de licencias](#14-third-party-licenses--transparency) +15. [Política de seguridad y objetivos de respuesta](#15-security-policy--slas) 16. [Verificación y suite de pruebas de contrato](#16-verification--contract-test-suite) -17. [Aviso legal alemán (§ 521 BGB)](#17-german-statutory-notice--521-bgb) +17. [Nota legal: § 521 BGB](#17-german-statutory-notice--521-bgb) 18. [Hoja de ruta y registro de cambios](#18-roadmap--changelog) --- @@ -69,8 +64,8 @@ Los asistentes de IA y los agentes LLM necesitan con frecuencia un lugar donde r `llm-note` ofrece el término medio arquitectónico ideal: - **Cero dependencias externas en tiempo de ejecución**: Construido íntegramente sobre la biblioteca estándar de Python (`sqlite3`, `http.server`, `urllib`, `argparse`, `json`, `pathlib`). -- **Flexibilidad de doble almacén**: Combina entradas de pensamiento estructuradas en SQLite (`data/notes.db`) con bandejas de entrada de texto plano editables por personas (`notebooks/*.txt`). -- **Procedencia de la extracción de BACH**: Desacoplado limpiamente del código del asistente de escritorio BACH (en concreto Notizblock y Denkarium) y liberado como código abierto bajo la licencia permisiva MIT. +- **Flexibilidad de doble almacén**: Combina entradas de pensamiento en SQLite (archivo predeterminado de la CLI: `llm-note.db`; ruta configurable) con bandejas de entrada de texto plano editables (`notebooks/*.txt`). +- **Procedencia de la extracción de BACH**: Desacoplado limpiamente del [código del asistente de escritorio BACH](https://github.com/ellmos-ai/bach), en concreto Notizblock y Denkarium, y publicado bajo la licencia permisiva MIT. --- @@ -84,7 +79,7 @@ Los asistentes de IA y los agentes LLM necesitan con frecuencia un lugar donde r - **Bandejas de entrada de cuadernos de texto plano (`FileNotebookStore`)**: Gestiona notas portables de texto plano con marcadores de categorización `#NB:` y bloqueo atómico de archivos entre procesos. - **Interfaz web Denkarium integrada**: Interfaz de navegador de bucle local (loopback), sin instalación, enlazada estrictamente a `127.0.0.1` mediante `http.server` de la biblioteca estándar y fuentes del sistema. - **Traducción multilingüe**: Localización nativa de mensajes en 6 idiomas: inglés, alemán, español, chino simplificado, japonés y ruso. -- **Skill de agente listo para usar**: El archivo incluido `skills/llm-note/SKILL.md` está listo para que los agentes autónomos lo descubran e invoquen de inmediato. +- **Skill de agente en el repositorio fuente**: El repositorio fuente contiene `skills/llm-note/SKILL.md`; `pyproject.toml` empaqueta solo `llm_note`, por lo que el wheel no incluye esa ruta fuente. - **Búsqueda determinista**: Búsquedas de subcadenas literales sin sorpresas por comodines, con límites estrictos de consulta (`0` a `1000`). --- @@ -112,7 +107,7 @@ graph TD end subgraph LocalStorage["Capa de almacenamiento local"] - DB[("data/notes.db
(registro de pensamientos SQLite)")] + DB[("llm-note.db
(registro de pensamientos SQLite; valor predeterminado de CLI)")] Notebooks["notebooks/*.txt
(bandejas de entrada de texto plano)"] LockFile[".llm-note.lock (coordinación atómica)"] end @@ -181,7 +176,7 @@ sequenceDiagram | ID de persona | Persona objetivo | Necesidad principal | Valor clave aportado | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **Creadores de agentes autónomos** | Memoria ligera de pensamientos que sobreviva a los reinicios de contexto del LLM | Almacén SQLite sin dependencias, integrable al instante | -| `[PERSONA-02]` | **Desarrolladores atentos a la privacidad** | Toma de notas y bandejas de entrada aisladas de la red y sin salida de datos | Funcionamiento 100 % local sin telemetría ni llamadas de red | +| `[PERSONA-02]` | **Desarrolladores atentos a la privacidad** | Notas SQLite locales y bandejas de texto sin un servicio de notas alojado | Almacenamiento local primero; la política del host controla el acceso a la red | | `[PERSONA-03]` | **Usuarios de asistentes de IA de escritorio** | Navegador visual instantáneo de pensamientos sin Node/Electron | Interfaz Denkarium integrada en loopback (`127.0.0.1`) | | `[PERSONA-04]` | **Investigadores de ciencia abierta** | Registros de pensamientos y experimentos auditables y rastreables con Git | Bandejas de entrada de texto plano y bases de datos SQLite estándar de un solo archivo | @@ -202,14 +197,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. Motor de almacenamiento** | **SQLite + TXT** | Archivos Markdown | SQLite / sincronización | Embeddings vectoriales | Un único archivo SQLite | | **2. Dependencias en tiempo de ejecución** | **0 (solo stdlib)** | Electron / Node | Electron / BD | C++ / Py pesados | 0 (binario C) | -| **3. Salida de red** | **Cero / aislado de la red** | Los plugins pueden filtrar datos | Servicio de sincronización | API remota / en la nube | Cero / local | +| **3. Requisitos de red** | **Almacenamiento local; se aplica la política del host** | No evaluado | No evaluado | No evaluado | No evaluado | | **4. API de Python para agentes** | **Nativa de primera clase** | REST de la comunidad | API de la comunidad | Cliente complejo | Requiere SQL puro | | **5. Interfaz web integrada** | **Integrada (127.0.0.1)** | Aplicación de escritorio | Aplicación de escritorio | SaaS aparte | Ninguna | | **6. Sincronización de bandeja de texto plano** | **Integrada (`#NB:`)** | Carpetas manuales | Importaciones manuales | N/D | Scripts manuales | | **7. Motor multilingüe** | **6 configuraciones regionales incluidas** | Paquete de la comunidad | Paquete de la comunidad | Centrado en inglés | Solo inglés | -| **8. Privilegio de ejecución** | **RunAsInvoker** | Usuario / escritorio | Usuario / escritorio | Docker / nube | Usuario | -| **9. Empaquetado como skill de agente** | **SKILL.md incluido** | De terceros | De terceros | Código a medida | Ninguno | -| **10. SLA de respuesta de seguridad** | **48 h / 5 d formal** | Comunidad | Comunidad | Solo empresarial | Dominio público | +| **8. Permisos del proceso** | **Hereda los permisos del proceso iniciador** | No evaluado | No evaluado | No evaluado | No evaluado | +| **9. Fuente del skill de agente** | **Repositorio fuente; no en el wheel** | De terceros | De terceros | Código a medida | Ninguno | +| **10. Información sobre respuesta de seguridad** | **Objetivos del mantenedor en SECURITY.md** | No evaluado | No evaluado | No evaluado | No evaluado | --- @@ -217,20 +212,20 @@ sequenceDiagram -## 7. Gobernanza e invariantes de ejecución +## 7. Gobernanza y notas de implementación -El motor `llm-note` opera bajo diez invariantes arquitectónicos inmutables: +Los puntos siguientes describen características actuales de implementación basadas en el código fuente. No son garantías inmutables ni una certificación de seguridad independiente: -- `INV-LOCAL-01`: **100 % local primero y cero salida de datos**: sin solicitudes de red salientes, sin telemetría, sin sincronización en la nube. -- `INV-LOCAL-02`: **Almacenamiento SQLite en un solo archivo**: base de datos ACID estructurada (`data/notes.db`) con diseños de tabla deterministas. +- `INV-LOCAL-01`: **Almacenamiento local primero**: las notas se guardan en SQLite local y archivos de texto plano; esto no bloquea el acceso a la red del host. +- `INV-LOCAL-02`: **Almacenamiento SQLite en un solo archivo**: base de datos ACID estructurada; el archivo predeterminado de la CLI es `llm-note.db` y la ruta se puede configurar. - `INV-LOCAL-03`: **Bandejas de entrada de cuadernos de texto plano**: bandejas de texto legibles por personas (`notebooks/*.txt`) con categorización `#NB:`. - `INV-LOCAL-04`: **Solo biblioteca estándar**: cero dependencias de terceros en tiempo de ejecución; funciona en cualquier entorno estándar de Python 3.10+. - `INV-LOCAL-05`: **Transferencias atómicas a prueba de fallos**: bloqueo entre procesos mediante `.llm-note.lock` y marcadores de idempotencia `#LLM-NOTE-ID`. - `INV-LOCAL-06`: **Interfaz web enlazada a loopback**: Denkarium escucha estrictamente en `127.0.0.1`; admite `--no-browser`. - `INV-LOCAL-07`: **I18N multilingüe**: 6 catálogos de localización incluidos: EN, DE, ES, ZH, JA, RU. -- `INV-LOCAL-08`: **Sin elevación (RunAsInvoker)**: opera íntegramente en el espacio de usuario sin privilegios; cero elevación administrativa. -- `INV-LOCAL-09`: **Empaquetado como skill de agente**: incluye una skill de agente completa (`skills/llm-note/SKILL.md`) para flujos de trabajo con LLM. -- `INV-LOCAL-10`: **SLA de seguridad de 48 horas**: compromisos formales de respuesta ante vulnerabilidades regulados por `SECURITY.md`. +- `INV-LOCAL-08`: **Permisos del proceso**: la aplicación no solicita elevación y hereda los permisos del proceso que la inicia. +- `INV-LOCAL-09`: **Fuente del skill de agente**: el repositorio fuente contiene [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md); `pyproject.toml` empaqueta solo `llm_note`, así que esa ruta fuente no se declara como contenido del wheel. +- `INV-LOCAL-10`: **Objetivos de respuesta del mantenedor**: `SECURITY.md` recoge objetivos de acuse de recibo y triaje; no son un SLA ni un plazo de corrección. --- @@ -240,7 +235,7 @@ El motor `llm-note` opera bajo diez invariantes arquitectónicos inmutables: ## 8. Guía de la interfaz web local Denkarium -La interfaz Denkarium ofrece un panel visual de pensamientos instantáneo y sin instalación: +La interfaz Denkarium ofrece un panel visual de pensamientos instantáneo y sin instalación. Elige uno de los seis idiomas en el menú «Idioma». La elección es independiente para cada navegador y se guarda en su almacenamiento local. Al iniciar la GUI con un `--locale` explícito, ese valor tiene prioridad para el idioma inicial; si no se indica, se usa la elección guardada y, como alternativa, inglés. ```bash # Iniciar Denkarium con la configuración por defecto (abre http://127.0.0.1:8000/) @@ -283,7 +278,7 @@ Esto proporciona el comando `llm-note` y el paquete de Python `llm_note`. ```bash # Escribir una nota con categoría y estado de ánimo -llm-note write "Refactor caching layer" --cat dev --mood focused +llm-note write "Refactor caching layer" --cat dev --mood 4 # Leer notas recientes (límite por defecto: 10) llm-note read --limit 5 @@ -319,7 +314,7 @@ notes = NoteStore("data/notes.db") entry = notes.write( content="Implement deterministic seed for test suite", category="testing", - mood="neutral" + mood=4 ) print(f"Created entry #{entry.id} at {entry.created_at}") @@ -346,7 +341,7 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 11. Skill de agente e integración en flujos de trabajo -`llm-note` incluye una definición de skill de agente en [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Los agentes autónomos (como Claude Code, Antigravity o Codex) pueden invocar `llm-note` directamente para registrar observaciones persistentes, mantener borradores entre delegaciones a subagentes y conservar registros de auditoría. +El repositorio fuente contiene la definición del skill de agente [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). El wheel solo empaqueta `llm_note`, según [`pyproject.toml`](pyproject.toml), por lo que no se afirma que esa ruta fuente forme parte del wheel. Los agentes autónomos pueden invocar `llm-note` para registrar observaciones y mantener borradores. ```markdown # Ejemplo de invocación de herramienta por un agente @@ -375,16 +370,16 @@ Para guardar una observación de investigación provisional: ## 13. Matriz del ecosistema hermano -`llm-note` forma parte de la familia `doc-bricks` bajo el paraguas de código abierto `open-bricks`: +Los siguientes enlaces apuntan a repositorios relacionados del ecosistema ampliado; su inclusión no implica una integración directa con llm-note: | Proyecto | Enfoque y papel en el ecosistema | Enlace | | :--- | :--- | :--- | | **doc-bricks/llm-note** | Núcleo local-first de pensamientos y cuadernos para agentes | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | Análisis de activos multimodales, OCR y transcripción de documentos | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | Análisis determinista de correo electrónico y canalización de archivado conforme | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | Biblioteca personal de vídeo y música con listas inteligentes e historial de reproducción | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | Aplicación de la bandeja de Windows para iniciar las herramientas locales Universal Mail | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | Sincronización de directorios robusta y multiplataforma | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| Resolución de conflictos y gestor de bloqueos para carpetas en la nube | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | Catálogo general y herramientas abiertas fundamentales para desarrolladores | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | Retrasa operaciones de archivos en carpetas sincronizadas y verifica los reemplazos de copia/eliminación con SHA-256 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks organization profile** | Perfil de organización y catálogo general; no es un repositorio específico | [open-bricks en GitHub](https://github.com/open-bricks) | --- @@ -392,28 +387,26 @@ Para guardar una observación de investigación provisional: -## 14. Licencias de terceros y transparencia +## 14. Dependencias de terceros y alcance de licencias -`llm-note` tiene **0 dependencias externas en tiempo de ejecución**. Todas las operaciones centrales se apoyan exclusivamente en la biblioteca estándar de Python, bajo la [Python Software Foundation License](https://docs.python.org/3/license.html). - -- Auditoría completa de SBOM y transparencia de licencias: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- Verificación de cero copyleft: 100 % libre de código GPL, AGPL, LGPL y SSPL. -- Ejecución sin privilegios: Certificado para el espacio de usuario `RunAsInvoker`. +`pyproject.toml` no declara paquetes Python adicionales como dependencias de tiempo de ejecución. El núcleo utiliza la biblioteca estándar de Python y SQLite proporcionado por el entorno de Python. +- Notas de alcance limitado sobre dependencias declaradas directamente: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) y [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt). No son SBOM completos. +- Estas notas no certifican el estado de licencias de todos los árboles transitivos de dependencias de desarrollo o compilación. +- El proceso no solicita elevación administrativa y hereda los permisos del proceso que lo inicia; esto no es una certificación de plataforma. --- -## 15. Política de seguridad y SLA - -Mantenemos un proceso riguroso y formal de gestión de vulnerabilidades, documentado en [`SECURITY.md`](SECURITY.md): +## 15. Política de seguridad y objetivos de respuesta -- **Contrato de cero salida de datos**: El software no realiza ninguna llamada de red. Cualquier salida no autorizada se clasifica como defecto crítico. -- **SLA de respuesta de 48 horas**: Triaje inicial en 48 horas; plan de resolución en 5 días hábiles. -- **Contacto**: Informa de posibles problemas de seguridad de forma confidencial a `security@lukasgeiger.com`. +El canal de notificación y los objetivos de respuesta del mantenedor se describen en [`SECURITY.md`](SECURITY.md): +- **Límite de implementación:** el núcleo de notas usa almacenamiento local y la interfaz web opcional se vincula a loopback. La aplicación no bloquea el acceso de red del host ni crea un entorno aislado. +- **Objetivos de respuesta del mantenedor:** acuse de recibo en 48 horas e inicio del triaje en 5 días hábiles son objetivos, no un SLA ni un plazo de corrección prometido. +- **Contacto**: Envía informes confidenciales mediante el canal privado descrito en [SECURITY.md](SECURITY.md). --- @@ -441,12 +434,9 @@ python -m compileall -q . -## 17. Aviso legal alemán (§ 521 BGB) - -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. - -Este software de código abierto se proporciona de forma gratuita bajo la licencia MIT. De conformidad con el § 521 del Código Civil alemán (BGB), la responsabilidad legal por las cesiones gratuitas se limita al dolo y a la negligencia grave. +## 17. Nota legal: § 521 BGB +§ 521 BGB puede ser pertinente según las circunstancias concretas. Esta nota no determina si se aplica a una distribución específica ni qué consecuencias de responsabilidad se derivan. --- diff --git a/README_ja.md b/README_ja.md index 4340595..28ba588 100644 --- a/README_ja.md +++ b/README_ja.md @@ -7,11 +7,6 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Platform: Windows | Linux | macOS](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 30 Passed](https://img.shields.io/badge/Tests-30%20Passed%20%7C%20100%25-brightgreen.svg)](tests/) -[![Privacy: 100% Local First](https://img.shields.io/badge/Privacy-100%25%20Local--First-success.svg)](SECURITY.md) -[![Network: Zero Egress](https://img.shields.io/badge/Network-Zero%20Egress-blue.svg)](SECURITY.md) -[![Security: RunAsInvoker](https://img.shields.io/badge/Security-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Response](https://img.shields.io/badge/SLA-48h%20Response-blueviolet.svg)](SECURITY.md) [![Dependencies: 0 Stdlib Only](https://img.shields.io/badge/Dependencies-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code Style: Ruff](https://img.shields.io/badge/Code%20Style-Ruff-000000.svg)](https://github.com/astral-sh/ruff) [![Ecosystem: doc-bricks](https://img.shields.io/badge/Ecosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) @@ -23,7 +18,7 @@ *機械支援による翻訳です。正式な内容は英語版 README が優先されます。* > [!NOTE] -> **プライバシー最優先・ローカル専用**: `llm-note` は、ローカルの SQLite とプレーンテキストファイルだけで動作します。API キー、クラウドサーバー、ベクトルデータベースのオーバーヘッドは一切不要で、外部へのネットワークリクエストも行いません。安全で、エアギャップ環境にも対応し、プライバシーを重視する AI エージェントのワークフローに最適です。 +> **ローカル優先のノート保存:** `llm-note` はノートをローカルの SQLite とプレーンテキストファイルに保存します。コアのノート保存にホスト型ノートサービスや API キーは必要ありません。任意の Web インターフェースは loopback にバインドされ、ネットワークアクセスはホストの設定に従います。 --- @@ -35,17 +30,17 @@ 4. [ノートと転送のライフサイクルシーケンス](#4-note--transfer-lifecycle-sequence) 5. [対象ペルソナと発見しやすさ](#5-target-personas--discoverability) 6. [代替手段との比較マトリクス](#6-comparative-matrix-vs-alternatives) -7. [ガバナンスとランタイム不変条件](#7-governance--runtime-invariants) +7. [ガバナンスと実装上の説明](#7-governance--runtime-invariants) 8. [Denkarium ローカル Web GUI ガイド](#8-denkarium-local-web-gui-guide) 9. [CLI 完全リファレンスと例](#9-cli-complete-reference--examples) 10. [Python API ガイドとコード例](#10-python-api-guide--code-examples) 11. [エージェントスキルとワークフロー連携](#11-agent-skill--workflow-integration) 12. [ファイルベースのインボックスと転送セマンティクス](#12-file-based-inboxes--transfer-semantics) 13. [兄弟エコシステムマトリクス](#13-sibling-ecosystem-matrix) -14. [サードパーティライセンスと透明性](#14-third-party-licenses--transparency) -15. [セキュリティポリシーと SLA](#15-security-policy--slas) +14. [サードパーティ依存関係とライセンス範囲](#14-third-party-licenses--transparency) +15. [セキュリティポリシーと対応目標](#15-security-policy--slas) 16. [検証とコントラクトテストスイート](#16-verification--contract-test-suite) -17. [ドイツ法に基づく通知 (§ 521 BGB)](#17-german-statutory-notice--521-bgb) +17. [法的な説明: § 521 BGB](#17-german-statutory-notice--521-bgb) 18. [ロードマップと変更履歴](#18-roadmap--changelog) --- @@ -70,8 +65,8 @@ AI アシスタントや LLM エージェントは、決定事項を記録し、 `llm-note` は、理想的なアーキテクチャ上の中間点を提供します。 - **外部ランタイム依存ゼロ**: Python 標準ライブラリ (`sqlite3`、`http.server`、`urllib`、`argparse`、`json`、`pathlib`) のみで構築されています。 -- **デュアルストアの柔軟性**: 構造化された SQLite の思考エントリ (`data/notes.db`) と、人間が編集可能なプレーンテキストのインボックス (`notebooks/*.txt`) を組み合わせています。 -- **BACH 由来の出自**: BACH デスクトップアシスタントのコードベース(具体的には Notizblock と Denkarium)から明確に切り離され、寛容な MIT ライセンスの下でオープンソース化されています。 +- **デュアルストアの柔軟性**: 構造化された SQLite の思考エントリ (CLI の既定ファイルは `llm-note.db`、パスは設定可能) と、人間が編集可能なプレーンテキストのインボックス (`notebooks/*.txt`) を組み合わせています。 +- **BACH 由来の出自**: BACH デスクトップアシスタントの[コードベース](https://github.com/ellmos-ai/bach)(具体的には Notizblock と Denkarium)から明確に切り離され、寛容な MIT ライセンスの下で公開されています。 --- @@ -85,7 +80,7 @@ AI アシスタントや LLM エージェントは、決定事項を記録し、 - **プレーンテキストのノートブックインボックス (`FileNotebookStore`)**: `#NB:` による分類マーカーとアトミックなプロセス間ファイルロックを備えた、可搬性のあるプレーンテキストのノートを管理します。 - **組み込み Denkarium Web UI**: インストール不要のループバック専用ブラウザインターフェース。標準ライブラリの `http.server` とシステムフォントを使用し、厳密に `127.0.0.1` にのみバインドされます。 - **多言語ローカライズ**: 英語、ドイツ語、スペイン語、簡体字中国語、日本語、ロシア語の 6 言語でメッセージをネイティブにローカライズします。 -- **すぐに使えるエージェントスキル**: 同梱の `skills/llm-note/SKILL.md` により、自律型エージェントがすぐに発見・呼び出しできます。 +- **エージェントスキルのソース**: ソースリポジトリには `skills/llm-note/SKILL.md` があります。`pyproject.toml` がパッケージ化するのは `llm_note` のみで、このソースパスは wheel に含まれません。 - **決定論的な検索**: ワイルドカードによる予期せぬ挙動のない文字列そのままの部分一致検索で、クエリの上限は厳密に定められています (`0` ~ `1000`)。 --- @@ -113,7 +108,7 @@ graph TD end subgraph LocalStorage["ローカルストレージ層"] - DB[("data/notes.db
(SQLite 思考ログ)")] + DB[("llm-note.db
(SQLite 思考ログ; CLI 既定値)")] Notebooks["notebooks/*.txt
(プレーンテキストのインボックス)"] LockFile[".llm-note.lock (アトミックな調整)"] end @@ -182,7 +177,7 @@ sequenceDiagram | ペルソナ ID | 対象ペルソナ | 中心的なニーズ | 提供する主な価値 | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **自律型エージェントの開発者** | LLM のコンテキストリセットをまたぐ軽量な思考メモリ | すぐに組み込める、依存ゼロの SQLite ストア | -| `[PERSONA-02]` | **プライバシーを重視する開発者** | エアギャップ環境で外部送信ゼロのノート取りとインボックス | テレメトリもネットワーク呼び出しもない 100% ローカル動作 | +| `[PERSONA-02]` | **プライバシーを重視する開発者** | ホスト型ノートサービスを使わないローカル SQLite ノートとテキストインボックス | ローカル優先の保存。ネットワークアクセスはホストのポリシーに従います | | `[PERSONA-03]` | **デスクトップ AI アシスタントのユーザー** | Node/Electron なしで使える即時のビジュアル思考ブラウザ | 組み込みのループバック Denkarium GUI (`127.0.0.1`) | | `[PERSONA-04]` | **オープンサイエンスの研究者** | Git で追跡でき、監査可能な思考・実験ログ | プレーンテキストのインボックスと標準的な単一ファイルの SQLite データベース | @@ -203,14 +198,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. ストレージエンジン** | **SQLite + TXT** | Markdown ファイル | SQLite / 同期 | ベクトル埋め込み | 単一の SQLite ファイル | | **2. ランタイム依存** | **0(標準ライブラリのみ)** | Electron / Node | Electron / DB | 重量級の C++ / Py | 0(C バイナリ) | -| **3. ネットワーク外部送信** | **ゼロ / エアギャップ** | プラグインが漏らす可能性あり | 同期サービス | リモート / クラウド API | ゼロ / ローカル | +| **3. ネットワーク要件** | **ローカル保存。ホストのポリシーに従う** | 未評価 | 未評価 | 未評価 | 未評価 | | **4. エージェント向け Python API** | **ネイティブのファーストクラス** | コミュニティ製 REST | コミュニティ製 API | 複雑なクライアント | 生の SQL が必要 | | **5. 組み込み Web GUI** | **内蔵 (127.0.0.1)** | デスクトップアプリ | デスクトップアプリ | 別の SaaS | なし | | **6. プレーンテキストのインボックス同期** | **内蔵 (`#NB:`)** | 手動のフォルダ | 手動のインポート | 該当なし | 手動のスクリプト | | **7. 多言語エンジン** | **6 ロケール同梱** | コミュニティパック | コミュニティパック | 英語中心 | 英語のみ | -| **8. 実行権限** | **RunAsInvoker** | ユーザー / デスクトップ | ユーザー / デスクトップ | Docker / クラウド | ユーザー | -| **9. エージェントスキルのパッケージ化** | **SKILL.md を同梱** | サードパーティ | サードパーティ | 独自コード | なし | -| **10. セキュリティ対応 SLA** | **48 時間 / 5 日(正式)** | コミュニティ | コミュニティ | エンタープライズ限定 | パブリックドメイン | +| **8. プロセス権限** | **起動元プロセスの権限を継承** | 未評価 | 未評価 | 未評価 | 未評価 | +| **9. エージェントスキルのソース** | **ソースリポジトリ内; wheel には含まれない** | サードパーティ | サードパーティ | 独自コード | なし | +| **10. セキュリティ対応情報** | **SECURITY.md のメンテナー目標** | 未評価 | 未評価 | 未評価 | 未評価 | --- @@ -218,20 +213,20 @@ sequenceDiagram -## 7. ガバナンスとランタイム不変条件 +## 7. ガバナンスと実装上の説明 -`llm-note` エンジンは、変更不可能な 10 のアーキテクチャ不変条件の下で動作します。 +以下はソースコードで確認できる現在の実装上の特性です。不変の保証や第三者によるセキュリティ認証ではありません。 -- `INV-LOCAL-01`: **100% ローカルファーストかつ外部送信ゼロ** — 外部へのネットワークリクエスト、テレメトリ、クラウド同期は一切ありません。 -- `INV-LOCAL-02`: **SQLite 単一ファイルストレージ** — 決定論的なテーブルレイアウトを持つ構造化 ACID データベース (`data/notes.db`)。 +- `INV-LOCAL-01`: **ローカル優先の保存** — ノートはローカルの SQLite とプレーンテキストファイルに保存されます。これはホスト上のネットワークアクセスを遮断するものではありません。 +- `INV-LOCAL-02`: **SQLite 単一ファイルストレージ** — 構造化 ACID データベース。CLI の既定ファイルは `llm-note.db` で、パスは設定できます。 - `INV-LOCAL-03`: **プレーンテキストのノートブックインボックス** — `#NB:` による分類を備えた、人間が読めるテキストのインボックス (`notebooks/*.txt`)。 - `INV-LOCAL-04`: **標準ライブラリのみ** — サードパーティのランタイム依存はゼロで、標準的な Python 3.10+ のランタイムであればどこでも動作します。 - `INV-LOCAL-05`: **クラッシュ安全なアトミック転送** — `.llm-note.lock` によるプロセス間ロックと `#LLM-NOTE-ID` の冪等性マーカー。 - `INV-LOCAL-06`: **ループバックにバインドされた Web GUI** — Denkarium は厳密に `127.0.0.1` のみで待ち受けます。`--no-browser` に対応しています。 - `INV-LOCAL-07`: **多言語 I18N** — 6 つのローカライズカタログを同梱: EN、DE、ES、ZH、JA、RU。 -- `INV-LOCAL-08`: **RunAsInvoker による非昇格** — 完全に権限のないユーザー空間で動作し、管理者権限への昇格は一切ありません。 -- `INV-LOCAL-09`: **エージェントスキルのパッケージ化** — LLM ワークフロー向けに、完全なエージェントスキル (`skills/llm-note/SKILL.md`) を同梱しています。 -- `INV-LOCAL-10`: **48 時間セキュリティ SLA** — `SECURITY.md` に定められた、脆弱性対応に関する正式な約束。 +- `INV-LOCAL-08`: **プロセス権限** — アプリケーションは昇格を要求せず、起動元プロセスの権限を継承します。 +- `INV-LOCAL-09`: **エージェントスキルのソース** — ソースリポジトリには [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md) があります。`pyproject.toml` は `llm_note` のみをパッケージ化するため、このソースパスを wheel の内容とは記載しません。 +- `INV-LOCAL-10`: **メンテナーの対応目標** — `SECURITY.md` に受付確認と初期トリアージの目標を記載しています。SLA や修正期限の約束ではありません。 --- @@ -241,7 +236,7 @@ sequenceDiagram ## 8. Denkarium ローカル Web GUI ガイド -Denkarium GUI は、インストール不要で即座に使えるビジュアルな思考ダッシュボードを提供します。 +Denkarium GUI は、インストール不要で即座に使えるビジュアルな思考ダッシュボードを提供します。「言語」メニューで6つの言語から選択します。選択はブラウザーごとに行われ、そのブラウザーのローカルストレージに保存されます。GUIの起動時に `--locale` を明示すると、その値が初期言語として優先されます。指定がない場合は、保存されたブラウザーの選択を使い、未選択なら英語になります。 ```bash # デフォルト設定で Denkarium を起動(http://127.0.0.1:8000/ を開きます) @@ -284,7 +279,7 @@ git clone https://github.com/doc-bricks/llm-note.git && cd llm-note && pip insta ```bash # カテゴリと気分を付けてノートを書く -llm-note write "Refactor caching layer" --cat dev --mood focused +llm-note write "Refactor caching layer" --cat dev --mood 4 # 最近のノートを読む(デフォルトの上限は 10) llm-note read --limit 5 @@ -320,7 +315,7 @@ notes = NoteStore("data/notes.db") entry = notes.write( content="Implement deterministic seed for test suite", category="testing", - mood="neutral" + mood=4 ) print(f"Created entry #{entry.id} at {entry.created_at}") @@ -347,7 +342,7 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 11. エージェントスキルとワークフロー連携 -`llm-note` には、[`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md) にエージェントスキル定義が含まれています。自律型エージェント(Claude Code、Antigravity、Codex など)は `llm-note` を直接呼び出して、永続的な所見を記録し、サブエージェントへの委任をまたいでスクラッチパッドを維持し、監査ログを保持できます。 +ソースリポジトリにはエージェントスキル定義 [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md) があります。`pyproject.toml` がパッケージ化するのは `llm_note` のみなので、このソースパスは wheel に含まれるとは記載しません。エージェントは `llm-note` を呼び出して観察内容や下書きを記録できます。 ```markdown # Agent Tool Invocation Example @@ -376,16 +371,16 @@ To save an interim research observation: ## 13. 兄弟エコシステムマトリクス -`llm-note` は、`open-bricks` オープンソース傘下の `doc-bricks` ファミリーの一員です。 +以下は広いエコシステム内の関連リポジトリです。掲載は llm-note との直接連携を示すものではありません。 | プロジェクト | エコシステムにおける焦点と役割 | リンク | | :--- | :--- | :--- | | **doc-bricks/llm-note** | エージェント向けのローカルファーストな思考・ノートブックのコア | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | マルチモーダルなアセット分析、OCR、ドキュメントの文字起こし | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | 決定論的なメール解析とコンプライアンスに準拠したアーカイブのパイプライン | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | スマートプレイリストとストリーミング視聴履歴を備えた、個人用の動画・音楽ライブラリ | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | ローカルの Universal Mail ツールを起動する Windows トレイアプリ | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | 堅牢なクロスプラットフォームのディレクトリ同期 | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| クラウドフォルダ向けの競合解決とロックマネージャー | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | 傘下のカタログと、基盤となるオープンな開発者ツール | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | クラウド同期フォルダのファイル操作を遅延実行し、SHA-256でコピー/削除フォールバックを検証します | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks 組織プロフィール** | 組織プロフィールとアンブレラカタログであり、個別のリポジトリではありません | [open-bricks on GitHub](https://github.com/open-bricks) | --- @@ -393,28 +388,26 @@ To save an interim research observation: -## 14. サードパーティライセンスと透明性 +## 14. サードパーティ依存関係とライセンス範囲 -`llm-note` の外部ランタイム依存は **0** です。すべてのコア処理は、[Python Software Foundation License](https://docs.python.org/3/license.html) の下にある Python 標準ライブラリだけに依存しています。 - -- SBOM とライセンス透明性の完全な監査: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- コピーレフトゼロの検証: GPL、AGPL、LGPL、SSPL のコードを 100% 含みません。 -- 権限のない実行: `RunAsInvoker` のユーザー空間向けに認定されています。 +`pyproject.toml` は追加の Python ランタイムパッケージ依存を宣言していません。コアは Python 標準ライブラリと Python 環境が提供する SQLite を使用します。 +- 直接宣言された依存関係に関する限定的な説明: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) と [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt)。完全な SBOM ではありません。 +- これらの依存関係メモは、推移的なビルド/開発依存関係全体のライセンス状態を認証しません。 +- プロセスは管理者権限への昇格を要求せず、起動元プロセスの権限を継承します。プラットフォーム認証ではありません。 --- -## 15. セキュリティポリシーと SLA - -[`SECURITY.md`](SECURITY.md) に記載された、厳格で正式な脆弱性管理プロセスを維持しています。 +## 15. セキュリティポリシーと対応目標 -- **外部送信ゼロの契約**: このソフトウェアはネットワーク呼び出しを一切行いません。無許可の外部送信は重大な欠陥として分類されます。 -- **48 時間対応 SLA**: 初期トリアージは 48 時間以内、解決計画は 5 営業日以内。 -- **連絡先**: セキュリティ上の問題の可能性は、`security@lukasgeiger.com` まで非公開でご報告ください。 +報告窓口とメンテナーの対応目標は [`SECURITY.md`](SECURITY.md) に記載しています。 +- **実装上の境界:** ノートコアはローカル保存を使用し、任意の Web インターフェースは loopback にバインドされます。アプリケーションはホストのネットワークアクセスを遮断せず、サンドボックスも提供しません。 +- **メンテナーの対応目標:** 48 時間以内の受領確認と 5 営業日以内の初期トリアージ開始は目標であり、SLA や修正期限の約束ではありません。 +- **連絡先:** セキュリティ報告は [SECURITY.md](SECURITY.md) に記載された非公開の報告方法をご利用ください。 --- @@ -442,12 +435,9 @@ python -m compileall -q . -## 17. ドイツ法に基づく通知 (§ 521 BGB) - -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. - -このオープンソースソフトウェアは、MIT ライセンスの下で無償で提供されます。ドイツ民法典 (BGB) § 521 に従い、無償提供に関する法定責任は、故意および重過失に限定されます。 +## 17. 法的な説明: § 521 BGB +§ 521 BGB が特定の提供に適用されるか、どのような責任上の結果が生じるかは、個別の事情によって異なります。この説明はその判断を行うものではありません。 --- diff --git a/README_ru.md b/README_ru.md index bab07f0..0bf53b8 100644 --- a/README_ru.md +++ b/README_ru.md @@ -7,11 +7,6 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Platform: Windows | Linux | macOS](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 30 Passed](https://img.shields.io/badge/Tests-30%20Passed%20%7C%20100%25-brightgreen.svg)](tests/) -[![Privacy: 100% Local First](https://img.shields.io/badge/Privacy-100%25%20Local--First-success.svg)](SECURITY.md) -[![Network: Zero Egress](https://img.shields.io/badge/Network-Zero%20Egress-blue.svg)](SECURITY.md) -[![Security: RunAsInvoker](https://img.shields.io/badge/Security-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Response](https://img.shields.io/badge/SLA-48h%20Response-blueviolet.svg)](SECURITY.md) [![Dependencies: 0 Stdlib Only](https://img.shields.io/badge/Dependencies-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code Style: Ruff](https://img.shields.io/badge/Code%20Style-Ruff-000000.svg)](https://github.com/astral-sh/ruff) [![Ecosystem: doc-bricks](https://img.shields.io/badge/Ecosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) @@ -23,7 +18,7 @@ *Перевод выполнен с помощью машинного перевода; приоритетной является английская версия README.* > [!NOTE] -> **Конфиденциальность прежде всего, только локально**: `llm-note` работает исключительно на локальной SQLite и обычных текстовых файлах. Ему не нужны ключи API, облачные серверы и накладные расходы векторной базы данных, и он не отправляет никаких исходящих сетевых запросов. Идеально подходит для защищённых, изолированных (air-gapped) и ориентированных на приватность рабочих процессов ИИ-агентов. +> **Локальное хранение заметок:** `llm-note` хранит заметки в локальной SQLite и текстовых файлах. Основному хранилищу заметок не нужны размещённый сервис заметок или ключ API. Дополнительный веб-интерфейс привязывается к loopback; сетевой доступ определяется настройками хоста. --- @@ -35,17 +30,17 @@ 4. [Последовательность жизненного цикла заметок и переноса](#4-note--transfer-lifecycle-sequence) 5. [Целевые персоны и поиск проекта](#5-target-personas--discoverability) 6. [Сравнительная матрица с альтернативами](#6-comparative-matrix-vs-alternatives) -7. [Управление и инварианты времени выполнения](#7-governance--runtime-invariants) +7. [Управление и заметки о реализации](#7-governance--runtime-invariants) 8. [Руководство по локальному веб-интерфейсу Denkarium](#8-denkarium-local-web-gui-guide) 9. [Полный справочник по CLI и примеры](#9-cli-complete-reference--examples) 10. [Руководство по Python API и примеры кода](#10-python-api-guide--code-examples) 11. [Навык агента и интеграция в рабочие процессы](#11-agent-skill--workflow-integration) 12. [Файловые входящие и семантика переноса](#12-file-based-inboxes--transfer-semantics) 13. [Матрица родственной экосистемы](#13-sibling-ecosystem-matrix) -14. [Лицензии сторонних компонентов и прозрачность](#14-third-party-licenses--transparency) -15. [Политика безопасности и SLA](#15-security-policy--slas) +14. [Сторонние зависимости и границы лицензионных сведений](#14-third-party-licenses--transparency) +15. [Политика безопасности и цели реагирования](#15-security-policy--slas) 16. [Проверка и набор контрактных тестов](#16-verification--contract-test-suite) -17. [Уведомление по немецкому законодательству (§ 521 BGB)](#17-german-statutory-notice--521-bgb) +17. [Правовое пояснение: § 521 BGB](#17-german-statutory-notice--521-bgb) 18. [Дорожная карта и журнал изменений](#18-roadmap--changelog) --- @@ -70,8 +65,8 @@ `llm-note` предлагает идеальный архитектурный компромисс: - **Ноль внешних зависимостей времени выполнения**: построен целиком на стандартной библиотеке Python (`sqlite3`, `http.server`, `urllib`, `argparse`, `json`, `pathlib`). -- **Гибкость двух хранилищ**: сочетает структурированные записи мыслей в SQLite (`data/notes.db`) с редактируемыми человеком текстовыми входящими (`notebooks/*.txt`). -- **Происхождение из BACH**: чисто отделён от кодовой базы настольного ассистента BACH (в частности, от Notizblock и Denkarium) и выпущен как открытое ПО под свободной лицензией MIT. +- **Гибкость двух хранилищ**: сочетает структурированные записи мыслей в SQLite (файл CLI по умолчанию — `llm-note.db`, путь настраивается) с редактируемыми человеком текстовыми входящими (`notebooks/*.txt`). +- **Происхождение из BACH**: чисто отделён от [кодовой базы настольного ассистента BACH](https://github.com/ellmos-ai/bach) (в частности, Notizblock и Denkarium) и выпущен под свободной лицензией MIT. --- @@ -85,7 +80,7 @@ - **Текстовые входящие блокнотов (`FileNotebookStore`)**: управляет переносимыми текстовыми заметками с маркерами категорий `#NB:` и атомарной межпроцессной блокировкой файлов. - **Встроенный веб-интерфейс Denkarium**: не требующий установки браузерный интерфейс, привязанный строго к `127.0.0.1` (loopback), на основе стандартного `http.server` и системных шрифтов. - **Многоязычная локализация**: встроенная локализация сообщений на 6 языках: английском, немецком, испанском, китайском (упрощённом), японском и русском. -- **Готовый навык агента**: в комплекте `skills/llm-note/SKILL.md` - автономные агенты могут сразу его обнаружить и использовать. +- **Навык агента в репозитории исходников**: репозиторий содержит `skills/llm-note/SKILL.md`; `pyproject.toml` упаковывает только `llm_note`, поэтому этот исходный путь не включён в wheel. - **Детерминированный поиск**: поиск буквальной подстроки без сюрпризов с подстановочными символами и со строгими ограничениями запроса (от `0` до `1000`). --- @@ -113,7 +108,7 @@ graph TD end subgraph LocalStorage["Слой локального хранилища"] - DB[("data/notes.db
(журнал мыслей SQLite)")] + DB[("llm-note.db
(журнал мыслей SQLite; CLI по умолчанию)")] Notebooks["notebooks/*.txt
(текстовые входящие)"] LockFile[".llm-note.lock (атомарная координация)"] end @@ -182,7 +177,7 @@ sequenceDiagram | ID персоны | Целевая персона | Основная потребность | Ключевая ценность | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **Разработчики автономных агентов** | Лёгкая память мыслей между сбросами контекста LLM | Хранилище SQLite без зависимостей, которое мгновенно встраивается | -| `[PERSONA-02]` | **Разработчики, заботящиеся о конфиденциальности** | Заметки и входящие в изолированной среде без исходящего трафика | 100% локальная работа без телеметрии и сетевых вызовов | +| `[PERSONA-02]` | **Разработчики, заботящиеся о конфиденциальности** | Локальные заметки SQLite и текстовые входящие без размещённого сервиса заметок | Локальное хранение; сетевой доступ контролируется политикой хоста | | `[PERSONA-03]` | **Пользователи настольных ИИ-ассистентов** | Мгновенный визуальный браузер мыслей без Node/Electron | Встроенный loopback-интерфейс Denkarium (`127.0.0.1`) | | `[PERSONA-04]` | **Исследователи открытой науки** | Журналы мыслей и экспериментов, отслеживаемые в Git и пригодные для аудита | Текстовые входящие и стандартные однофайловые базы данных SQLite | @@ -203,14 +198,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. Движок хранения** | **SQLite + TXT** | Файлы Markdown | SQLite / синхронизация | Векторные эмбеддинги | Один файл SQLite | | **2. Зависимости времени выполнения** | **0 (только stdlib)** | Electron / Node | Electron / БД | Тяжёлые C++ / Py | 0 (бинарник на C) | -| **3. Исходящий сетевой трафик** | **Нулевой / изолированная среда** | Плагины могут передавать данные | Служба синхронизации | Удалённый / облачный API | Нулевой / локально | +| **3. Сетевые требования** | **Локальное хранение; действует политика хоста** | Не оценивалось | Не оценивалось | Не оценивалось | Не оценивалось | | **4. Python API для агентов** | **Нативный, первоклассный** | REST от сообщества | API от сообщества | Сложный клиент | Требуется чистый SQL | | **5. Встроенный веб-интерфейс** | **Встроен (127.0.0.1)** | Настольное приложение | Настольное приложение | Отдельный SaaS | Нет | | **6. Синхронизация текстовых входящих** | **Встроена (`#NB:`)** | Ручные папки | Ручной импорт | Не применимо | Ручные скрипты | | **7. Многоязычный движок** | **6 встроенных локалей** | Пакет от сообщества | Пакет от сообщества | Ориентирован на английский | Только английский | -| **8. Привилегии выполнения** | **RunAsInvoker** | Пользователь / настольный режим | Пользователь / настольный режим | Docker / облако | Пользователь | -| **9. Упаковка навыка агента** | **SKILL.md в комплекте** | Сторонний | Сторонний | Собственный код | Нет | -| **10. SLA реагирования на уязвимости** | **48 ч / 5 дн., формально** | Сообщество | Сообщество | Только для предприятий | Общественное достояние | +| **8. Права процесса** | **Наследуются от запускающего процесса** | Не оценивалось | Не оценивалось | Не оценивалось | Не оценивалось | +| **9. Исходный навык агента** | **В репозитории; не в wheel** | Сторонний | Сторонний | Собственный код | Нет | +| **10. Информация о реагировании на уязвимости** | **Цели сопровождающего в SECURITY.md** | Не оценивалось | Не оценивалось | Не оценивалось | Не оценивалось | --- @@ -218,20 +213,20 @@ sequenceDiagram -## 7. Управление и инварианты времени выполнения +## 7. Управление и заметки о реализации -Движок `llm-note` работает в соответствии с десятью неизменными архитектурными инвариантами: +Ниже описаны текущие характеристики реализации, подтверждённые исходным кодом. Это не неизменные гарантии и не независимая сертификация безопасности: -- `INV-LOCAL-01`: **100% local-first и нулевой исходящий трафик** — никаких исходящих сетевых запросов, телеметрии и облачной синхронизации. -- `INV-LOCAL-02`: **Однофайловое хранилище SQLite** — структурированная база данных ACID (`data/notes.db`) с детерминированной схемой таблиц. +- `INV-LOCAL-01`: **Локальное хранение прежде всего** — заметки хранятся в локальной SQLite и текстовых файлах; это не блокирует сетевой доступ на уровне хоста. +- `INV-LOCAL-02`: **Однофайловое хранилище SQLite** — структурированная база данных ACID; файл CLI по умолчанию — `llm-note.db`, путь настраивается. - `INV-LOCAL-03`: **Текстовые входящие блокнотов** — читаемые человеком текстовые входящие (`notebooks/*.txt`) с категоризацией через `#NB:`. - `INV-LOCAL-04`: **Только стандартная библиотека** — ноль сторонних зависимостей времени выполнения; работает в любой стандартной среде Python 3.10+. - `INV-LOCAL-05`: **Атомарные переносы, устойчивые к сбоям** — межпроцессная блокировка через `.llm-note.lock` и маркеры идемпотентности `#LLM-NOTE-ID`. - `INV-LOCAL-06`: **Веб-интерфейс, привязанный к loopback** — Denkarium слушает строго `127.0.0.1`; поддерживается `--no-browser`. - `INV-LOCAL-07`: **Многоязычный I18N** — 6 встроенных каталогов локализации: EN, DE, ES, ZH, JA, RU. -- `INV-LOCAL-08`: **RunAsInvoker, без повышения привилегий** — работает целиком в непривилегированном пользовательском пространстве; никакого административного повышения. -- `INV-LOCAL-09`: **Упаковка навыка агента** — поставляется с полным навыком агента (`skills/llm-note/SKILL.md`) для рабочих процессов LLM. -- `INV-LOCAL-10`: **48-часовой SLA по безопасности** — формальные обязательства по реагированию на уязвимости, регулируемые `SECURITY.md`. +- `INV-LOCAL-08`: **Права процесса** — приложение не запрашивает повышение привилегий и наследует права запускающего процесса. +- `INV-LOCAL-09`: **Исходный навык агента** — репозиторий содержит [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md); `pyproject.toml` упаковывает только `llm_note`, поэтому исходный путь не заявлен как содержимое wheel. +- `INV-LOCAL-10`: **Цели сопровождающего по реагированию** — `SECURITY.md` содержит цели подтверждения получения и первичной оценки; это не SLA и не обещанный срок исправления. --- @@ -241,7 +236,7 @@ sequenceDiagram ## 8. Руководство по локальному веб-интерфейсу Denkarium -Интерфейс Denkarium - это мгновенная визуальная панель мыслей, не требующая установки: +Интерфейс Denkarium — это мгновенная визуальная панель мыслей, не требующая установки. Выберите один из шести языков в меню «Язык». Выбор хранится отдельно для каждого браузера в его локальном хранилище. При запуске GUI с явным параметром `--locale` он задаёт начальный язык; без него используется сохранённый выбор браузера, а по умолчанию — английский. ```bash # Запуск Denkarium с настройками по умолчанию (открывает http://127.0.0.1:8000/) @@ -284,7 +279,7 @@ git clone https://github.com/doc-bricks/llm-note.git && cd llm-note && pip insta ```bash # Написать заметку с категорией и настроением -llm-note write "Refactor caching layer" --cat dev --mood focused +llm-note write "Refactor caching layer" --cat dev --mood 4 # Прочитать недавние заметки (лимит по умолчанию - 10) llm-note read --limit 5 @@ -320,7 +315,7 @@ notes = NoteStore("data/notes.db") entry = notes.write( content="Implement deterministic seed for test suite", category="testing", - mood="neutral" + mood=4 ) print(f"Created entry #{entry.id} at {entry.created_at}") @@ -347,7 +342,7 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 11. Навык агента и интеграция в рабочие процессы -`llm-note` включает определение навыка агента в [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Автономные агенты (такие как Claude Code, Antigravity или Codex) могут напрямую вызывать `llm-note`, чтобы записывать устойчивые наблюдения, вести черновые заметки при делегировании субагентам и сохранять журналы аудита. +Репозиторий исходников содержит определение навыка агента [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md). Согласно [`pyproject.toml`](pyproject.toml), wheel включает только `llm_note`, поэтому этот исходный путь не заявляется как содержимое wheel. Агент может вызывать `llm-note`, чтобы сохранять наблюдения и черновики. ```markdown # Agent Tool Invocation Example @@ -376,16 +371,16 @@ To save an interim research observation: ## 13. Матрица родственной экосистемы -`llm-note` входит в семейство `doc-bricks` в рамках открытой экосистемы `open-bricks`: +Ниже перечислены связанные репозитории из более широкой экосистемы; само упоминание не означает прямую интеграцию с llm-note: | Проект | Фокус и роль в экосистеме | Ссылка | | :--- | :--- | :--- | | **doc-bricks/llm-note** | Local-first ядро мыслей и блокнотов для агентов | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | Мультимодальный анализ ресурсов, OCR и транскрибация документов | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | Детерминированный разбор электронной почты и конвейер архивирования с соблюдением требований | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | Личная библиотека видео и музыки со смарт-плейлистами и историей просмотра потокового видео | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | Приложение в системном трее Windows для запуска локальных инструментов Universal Mail | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | Надёжная кроссплатформенная синхронизация каталогов | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| Разрешение конфликтов и менеджер блокировок для облачных папок | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | Общий каталог и базовые открытые инструменты разработчика | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | Откладывает файловые операции в папках облачной синхронизации и проверяет копирование с последующим удалением с помощью SHA-256 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks organization profile** | Профиль организации и общий каталог, а не отдельный репозиторий | [open-bricks на GitHub](https://github.com/open-bricks) | --- @@ -393,28 +388,26 @@ To save an interim research observation: -## 14. Лицензии сторонних компонентов и прозрачность +## 14. Сторонние зависимости и границы лицензионных сведений -У `llm-note` **0 внешних зависимостей времени выполнения**. Все основные операции опираются исключительно на стандартную библиотеку Python, распространяемую по [лицензии Python Software Foundation](https://docs.python.org/3/license.html). - -- Полный аудит SBOM и прозрачности лицензий: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- Проверка отсутствия копилефта: 100% свободно от кода под GPL, AGPL, LGPL и SSPL. -- Выполнение без привилегий: сертифицировано для пользовательского пространства `RunAsInvoker`. +`pyproject.toml` не объявляет дополнительные пакеты Python как зависимости времени выполнения. Ядро использует стандартную библиотеку Python и SQLite из среды Python. +- Ограниченные сведения о прямо объявленных зависимостях: [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) и [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt). Это не полные SBOM. +- Эти заметки не подтверждают лицензионный статус всех транзитивных деревьев сборочных и разработческих зависимостей. +- Процесс не запрашивает административное повышение и наследует права запускающего процесса; это не сертификация платформы. --- -## 15. Политика безопасности и SLA - -Мы придерживаемся строгого формального процесса управления уязвимостями, описанного в [`SECURITY.md`](SECURITY.md): +## 15. Политика безопасности и цели реагирования -- **Контракт нулевого исходящего трафика**: программа не выполняет сетевых вызовов. Любая несанкционированная отправка данных классифицируется как критический дефект. -- **SLA ответа в течение 48 часов**: первичная оценка в течение 48 часов; план решения в течение 5 рабочих дней. -- **Контакт**: о возможных проблемах безопасности сообщайте конфиденциально на `security@lukasgeiger.com`. +Канал для сообщений и цели реагирования сопровождающего описаны в [`SECURITY.md`](SECURITY.md): +- **Граница реализации:** ядро заметок использует локальное хранилище, а дополнительный веб-интерфейс привязывается к loopback. Приложение не блокирует сетевой доступ хоста и не предоставляет песочницу. +- **Цели сопровождающего:** подтверждение получения в течение 48 часов и начало первичной оценки в течение 5 рабочих дней — это цели, а не SLA или обещанный срок исправления. +- **Контакт:** конфиденциальные сообщения о безопасности отправляйте способом, описанным в [SECURITY.md](SECURITY.md). --- @@ -442,12 +435,9 @@ python -m compileall -q . -## 17. Уведомление по немецкому законодательству (§ 521 BGB) - -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. - -Это программное обеспечение с открытым исходным кодом предоставляется бесплатно на условиях лицензии MIT. В соответствии с § 521 Гражданского уложения Германии (BGB) установленная законом ответственность при безвозмездном предоставлении ограничивается умыслом и грубой неосторожностью. +## 17. Правовое пояснение: § 521 BGB +Применимость § 521 BGB к конкретному предоставлению и его возможные последствия для ответственности зависят от обстоятельств. Это пояснение не определяет их. --- diff --git a/README_zh-Hans.md b/README_zh-Hans.md index aa509be..2ededd2 100644 --- a/README_zh-Hans.md +++ b/README_zh-Hans.md @@ -7,11 +7,6 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![Python 3.10-3.13](https://img.shields.io/badge/Python-3.10%20--%203.13-blue.svg)](pyproject.toml) [![Platform: Windows | Linux | macOS](https://img.shields.io/badge/Platform-Windows%20%7C%20Linux%20%7C%20macOS-lightgrey.svg)](pyproject.toml) -[![Tests: 30 Passed](https://img.shields.io/badge/Tests-30%20Passed%20%7C%20100%25-brightgreen.svg)](tests/) -[![Privacy: 100% Local First](https://img.shields.io/badge/Privacy-100%25%20Local--First-success.svg)](SECURITY.md) -[![Network: Zero Egress](https://img.shields.io/badge/Network-Zero%20Egress-blue.svg)](SECURITY.md) -[![Security: RunAsInvoker](https://img.shields.io/badge/Security-RunAsInvoker-orange.svg)](THIRD_PARTY_LICENSES.md) -[![SLA: 48h Response](https://img.shields.io/badge/SLA-48h%20Response-blueviolet.svg)](SECURITY.md) [![Dependencies: 0 Stdlib Only](https://img.shields.io/badge/Dependencies-0%20(Stdlib)-brightgreen.svg)](THIRD_PARTY_LICENSES.md) [![Code Style: Ruff](https://img.shields.io/badge/Code%20Style-Ruff-000000.svg)](https://github.com/astral-sh/ruff) [![Ecosystem: doc-bricks](https://img.shields.io/badge/Ecosystem-doc--bricks-0055ff.svg)](https://github.com/doc-bricks) @@ -22,7 +17,7 @@ *机器辅助翻译;以英文 README 为准。* > [!NOTE] -> **隐私优先,仅限本地**:`llm-note` 完全基于本地 SQLite 和纯文本文件运行。它不需要 API 密钥、云服务器或向量数据库的额外开销,也不会发起任何出站网络请求。非常适合安全、物理隔离(air-gapped)且注重隐私的 AI 智能体工作流。 +> **本地优先的笔记存储:** `llm-note` 将笔记保存在本地 SQLite 和纯文本文件中。核心笔记存储无需托管笔记服务或 API 密钥。可选 Web 界面绑定到 loopback;网络访问由主机设置控制。 --- @@ -34,17 +29,17 @@ 4. [笔记与转移生命周期时序](#4-note--transfer-lifecycle-sequence) 5. [目标用户画像与可发现性](#5-target-personas--discoverability) 6. [与替代方案的对比矩阵](#6-comparative-matrix-vs-alternatives) -7. [治理与运行时不变量](#7-governance--runtime-invariants) +7. [治理与实现说明](#7-governance--runtime-invariants) 8. [Denkarium 本地 Web 界面指南](#8-denkarium-local-web-gui-guide) 9. [CLI 完整参考与示例](#9-cli-complete-reference--examples) 10. [Python API 指南与代码示例](#10-python-api-guide--code-examples) 11. [智能体 Skill 与工作流集成](#11-agent-skill--workflow-integration) 12. [基于文件的收件箱与转移语义](#12-file-based-inboxes--transfer-semantics) 13. [同类生态系统矩阵](#13-sibling-ecosystem-matrix) -14. [第三方许可证与透明度](#14-third-party-licenses--transparency) -15. [安全策略与 SLA](#15-security-policy--slas) +14. [第三方依赖与许可证范围](#14-third-party-licenses--transparency) +15. [安全策略与响应目标](#15-security-policy--slas) 16. [验证与契约测试套件](#16-verification--contract-test-suite) -17. [德国法定声明(§ 521 BGB)](#17-german-statutory-notice--521-bgb) +17. [法律说明:§ 521 BGB](#17-german-statutory-notice--521-bgb) 18. [路线图与变更日志](#18-roadmap--changelog) --- @@ -69,8 +64,8 @@ AI 助手和 LLM 智能体经常需要一个地方来记录决策、捕捉上下 `llm-note` 提供了理想的架构折中方案: - **零外部运行时依赖**:完全基于 Python 标准库构建(`sqlite3`、`http.server`、`urllib`、`argparse`、`json`、`pathlib`)。 -- **双存储灵活性**:将结构化的 SQLite 想法条目(`data/notes.db`)与可由人工编辑的纯文本收件箱(`notebooks/*.txt`)结合在一起。 -- **BACH 提取溯源**:与 BACH 桌面助手代码库(特别是 Notizblock 和 Denkarium)干净地解耦,并以宽松的 MIT 许可证开源。 +- **双存储灵活性**:将结构化的 SQLite 想法条目(CLI 默认文件为 `llm-note.db`,路径可配置)与可由人工编辑的纯文本收件箱(`notebooks/*.txt`)结合在一起。 +- **BACH 提取溯源**:与 [BACH 桌面助手代码库](https://github.com/ellmos-ai/bach)(特别是 Notizblock 和 Denkarium)干净地解耦,并以宽松的 MIT 许可证开源。 --- @@ -84,7 +79,7 @@ AI 助手和 LLM 智能体经常需要一个地方来记录决策、捕捉上下 - **纯文本笔记本收件箱(`FileNotebookStore`)**:通过 `#NB:` 分类标记和原子级跨进程文件锁,管理可移植的纯文本笔记。 - **内嵌 Denkarium Web 界面**:免安装的回环(loopback)浏览器界面,使用标准库 `http.server` 和系统字体,严格绑定到 `127.0.0.1`。 - **多语言翻译**:原生支持 6 种语言的消息本地化:英语、德语、西班牙语、简体中文、日语和俄语。 -- **开箱即用的智能体 Skill**:内置 `skills/llm-note/SKILL.md`,可供自主智能体立即发现并调用。 +- **源代码仓库中的智能体 Skill**:源代码仓库包含 `skills/llm-note/SKILL.md`;`pyproject.toml` 只打包 `llm_note`,因此 wheel 不包含该源文件路径。 - **确定性搜索**:字面子串搜索,无通配符意外,并有严格的查询上限(`0` 到 `1000`)。 --- @@ -112,7 +107,7 @@ graph TD end subgraph LocalStorage["本地存储层"] - DB[("data/notes.db
(SQLite 想法日志)")] + DB[("llm-note.db
(SQLite 想法日志;CLI 默认)")] Notebooks["notebooks/*.txt
(纯文本收件箱)"] LockFile[".llm-note.lock (原子协调)"] end @@ -181,7 +176,7 @@ sequenceDiagram | 画像 ID | 目标用户画像 | 核心需求 | 提供的关键价值 | | :--- | :--- | :--- | :--- | | `[PERSONA-01]` | **自主智能体构建者** | 跨 LLM 上下文重置的轻量级想法记忆 | 零依赖的 SQLite 存储,可即刻嵌入 | -| `[PERSONA-02]` | **注重隐私的开发者** | 物理隔离、零外泄的笔记记录与收件箱 | 100% 本地运行,无遥测、无网络调用 | +| `[PERSONA-02]` | **注重隐私的开发者** | 无需托管笔记服务的本地 SQLite 笔记和文本收件箱 | 本地优先存储;网络访问由主机策略控制 | | `[PERSONA-03]` | **桌面 AI 助手用户** | 无需 Node/Electron 的即时可视化想法浏览器 | 内置回环 Denkarium 界面(`127.0.0.1`) | | `[PERSONA-04]` | **开放科学研究者** | 可由 Git 跟踪、可审计的想法与实验日志 | 纯文本收件箱与标准的单文件 SQLite 数据库 | @@ -202,14 +197,14 @@ sequenceDiagram | :--- | :---: | :---: | :---: | :---: | :---: | | **1. 存储引擎** | **SQLite + TXT** | Markdown 文件 | SQLite / 同步 | 向量嵌入 | 单个 SQLite 文件 | | **2. 运行时依赖** | **0(仅标准库)** | Electron / Node | Electron / 数据库 | 沉重的 C++ / Py | 0(C 二进制) | -| **3. 网络外发** | **零 / 物理隔离** | 插件可能泄露 | 同步服务 | 远程 / 云 API | 零 / 本地 | +| **3. 网络要求** | **本地存储;适用主机策略** | 未评估 | 未评估 | 未评估 | 未评估 | | **4. 智能体 Python API** | **原生一等公民** | 社区 REST | 社区 API | 复杂的客户端 | 需要编写原始 SQL | | **5. 内嵌 Web 界面** | **内置(127.0.0.1)** | 桌面应用 | 桌面应用 | 独立的 SaaS | 无 | | **6. 纯文本收件箱同步** | **内置(`#NB:`)** | 手动文件夹 | 手动导入 | 不适用 | 手动脚本 | | **7. 多语言引擎** | **内置 6 种语言区域** | 社区包 | 社区包 | 以英语为中心 | 仅英语 | -| **8. 执行权限** | **RunAsInvoker** | 用户 / 桌面 | 用户 / 桌面 | Docker / 云 | 用户 | -| **9. 智能体 Skill 打包** | **内置 SKILL.md** | 第三方 | 第三方 | 自定义代码 | 无 | -| **10. 安全响应 SLA** | **48 小时 / 5 天,正式承诺** | 社区 | 社区 | 仅限企业版 | 公有领域 | +| **8. 进程权限** | **继承调用进程权限** | 未评估 | 未评估 | 未评估 | 未评估 | +| **9. 智能体 Skill 来源** | **源代码仓库;不在 wheel 中** | 第三方 | 第三方 | 自定义代码 | 无 | +| **10. 安全响应信息** | **见 SECURITY.md 中的维护者目标** | 未评估 | 未评估 | 未评估 | 未评估 | --- @@ -217,20 +212,20 @@ sequenceDiagram -## 7. 治理与运行时不变量 +## 7. 治理与实现说明 -`llm-note` 引擎遵循十条不可变的架构不变量: +以下内容依据源代码描述当前实现特征,不构成不可变保证或独立安全认证: -- `INV-LOCAL-01`:**100% 本地优先与零外泄**——无出站网络请求、无遥测、无云同步。 -- `INV-LOCAL-02`:**SQLite 单文件存储**——结构化 ACID 数据库(`data/notes.db`),表布局具有确定性。 +- `INV-LOCAL-01`:**本地优先存储**——笔记保存在本地 SQLite 和纯文本文件中;这不会阻止主机层面的网络访问。 +- `INV-LOCAL-02`:**SQLite 单文件存储**——结构化 ACID 数据库;CLI 默认文件为 `llm-note.db`,路径可配置。 - `INV-LOCAL-03`:**纯文本笔记本收件箱**——人类可读的文本收件箱(`notebooks/*.txt`),使用 `#NB:` 分类。 - `INV-LOCAL-04`:**仅使用标准库**——零第三方运行时依赖;可在任何标准 Python 3.10+ 运行时上运行。 - `INV-LOCAL-05`:**崩溃安全的原子转移**——通过 `.llm-note.lock` 实现跨进程加锁,并使用 `#LLM-NOTE-ID` 幂等标记。 - `INV-LOCAL-06`:**绑定回环的 Web 界面**——Denkarium 严格只监听 `127.0.0.1`;支持 `--no-browser`。 - `INV-LOCAL-07`:**多语言 I18N**——内置 6 个本地化目录:EN、DE、ES、ZH、JA、RU。 -- `INV-LOCAL-08`:**RunAsInvoker 无提权**——完全在无特权的用户空间运行;零管理员提权。 -- `INV-LOCAL-09`:**智能体 Skill 打包**——为 LLM 工作流提供完整的智能体 Skill(`skills/llm-note/SKILL.md`)。 -- `INV-LOCAL-10`:**48 小时安全 SLA**——由 `SECURITY.md` 规定的正式漏洞响应承诺。 +- `INV-LOCAL-08`:**进程权限**——应用不会请求提权,并继承启动它的进程权限。 +- `INV-LOCAL-09`:**智能体 Skill 来源**——源代码仓库包含 [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md);`pyproject.toml` 只打包 `llm_note`,因此不声称 wheel 包含该源文件路径。 +- `INV-LOCAL-10`:**维护者响应目标**——`SECURITY.md` 列出收件确认和初步分诊目标;这不是 SLA,也不承诺修复期限。 --- @@ -240,7 +235,7 @@ sequenceDiagram ## 8. Denkarium 本地 Web 界面指南 -Denkarium 界面提供即时、免安装的可视化想法仪表盘: +Denkarium 界面提供即时、免安装的可视化想法仪表盘。在“语言”菜单中选择六种语言之一。选择按浏览器分别保存,并存储在该浏览器的本地存储中。启动 GUI 时若显式指定 `--locale`,该值优先作为初始语言;未指定时使用浏览器保存的选择,默认回退到英语。 ```bash # 以默认设置启动 Denkarium(打开 http://127.0.0.1:8000/) @@ -283,7 +278,7 @@ git clone https://github.com/doc-bricks/llm-note.git && cd llm-note && pip insta ```bash # 写入带有类别和心情的笔记 -llm-note write "Refactor caching layer" --cat dev --mood focused +llm-note write "Refactor caching layer" --cat dev --mood 4 # 读取最近的笔记(默认上限为 10 条) llm-note read --limit 5 @@ -319,7 +314,7 @@ notes = NoteStore("data/notes.db") entry = notes.write( content="Implement deterministic seed for test suite", category="testing", - mood="neutral" + mood=4 ) print(f"Created entry #{entry.id} at {entry.created_at}") @@ -346,7 +341,7 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 11. 智能体 Skill 与工作流集成 -`llm-note` 在 [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md) 中包含一份智能体 Skill 定义。自主智能体(例如 Claude Code、Antigravity 或 Codex)可以直接调用 `llm-note` 来记录持久化的观察结果、在子智能体委派之间维护草稿区,并保留审计日志。 +源代码仓库包含智能体 Skill 定义 [`skills/llm-note/SKILL.md`](skills/llm-note/SKILL.md)。根据 [`pyproject.toml`](pyproject.toml),wheel 只打包 `llm_note`,因此不声称该源文件路径属于 wheel 内容。自主智能体可以调用 `llm-note` 来记录观察结果并维护草稿。 ```markdown # 智能体工具调用示例 @@ -375,16 +370,16 @@ print(f"Transferred {transferred} entries to topic notebooks.") ## 13. 同类生态系统矩阵 -`llm-note` 是 `open-bricks` 开源伞下 `doc-bricks` 家族的一员: +以下是更广泛生态中的相关仓库;列出这些链接并不表示它们与 llm-note 直接集成: | 项目 | 定位与在生态系统中的角色 | 链接 | | :--- | :--- | :--- | | **doc-bricks/llm-note** | 面向智能体的本地优先想法与笔记本核心 | [doc-bricks/llm-note](https://github.com/doc-bricks/llm-note) | -| **doc-bricks/MediaBrain** | 多模态资产分析、OCR 与文档转录 | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | -| **doc-bricks/MailProcessor** | 确定性的电子邮件解析与合规归档流水线 | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | +| **doc-bricks/MediaBrain** | 个人视频与音乐库,提供智能播放列表和流媒体观看历史 | [doc-bricks/MediaBrain](https://github.com/doc-bricks/MediaBrain) | +| **doc-bricks/MailProcessor** | 用于启动本地 Universal Mail 工具的 Windows 系统托盘应用 | [doc-bricks/MailProcessor](https://github.com/doc-bricks/MailProcessor) | | **file-bricks/ProSync** | 稳健的跨平台目录同步 | [file-bricks/ProSync](https://github.com/file-bricks/ProSync) | -| **file-bricks/CloudLockFixer**| 云文件夹的冲突解决与锁管理器 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | -| **open-bricks/open-bricks** | 总目录与基础性的开放开发者工具 | [open-bricks/open-bricks](https://github.com/open-bricks) | +| **file-bricks/CloudLockFixer** | 延迟处理云同步文件夹中的文件操作,并用 SHA-256 校验复制/删除回退 | [file-bricks/CloudLockFixer](https://github.com/file-bricks/CloudLockFixer) | +| **open-bricks 组织主页** | 组织主页和总目录;不是某个具体仓库 | [open-bricks on GitHub](https://github.com/open-bricks) | --- @@ -392,28 +387,26 @@ print(f"Transferred {transferred} entries to topic notebooks.") -## 14. 第三方许可证与透明度 +## 14. 第三方依赖与许可证范围 -`llm-note` 有 **0 个外部运行时依赖**。所有核心操作仅依赖 Python 标准库,其许可证为 [Python Software Foundation License](https://docs.python.org/3/license.html)。 - -- 完整的 SBOM 与许可证透明度审计:[`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) -- 零 Copyleft 验证:100% 不含 GPL、AGPL、LGPL 和 SSPL 代码。 -- 无特权执行:已认证适用于 `RunAsInvoker` 用户空间。 +`pyproject.toml` 未声明额外的 Python 运行时软件包依赖。核心使用 Python 标准库和 Python 环境提供的 SQLite。 +- 直接声明依赖的有限范围说明:[`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) 和 [`THIRD_PARTY_LICENSES.txt`](THIRD_PARTY_LICENSES.txt)。它们不是完整 SBOM。 +- 这些说明不认证完整传递性构建或开发依赖树的许可证状态。 +- 进程不会请求管理员提权,并继承启动它的进程权限;这不是平台认证。 --- -## 15. 安全策略与 SLA - -我们维护严格、正式的漏洞管理流程,详见 [`SECURITY.md`](SECURITY.md): +## 15. 安全策略与响应目标 -- **零外泄契约**:本软件不进行任何网络调用。任何未经授权的外发都被归类为严重缺陷。 -- **48 小时响应 SLA**:48 小时内完成初步分诊;5 个工作日内给出解决方案。 -- **联系方式**:请将潜在的安全问题保密地报告至 `security@lukasgeiger.com`。 +报告渠道和维护者响应目标见 [`SECURITY.md`](SECURITY.md): +- **实现边界:**笔记核心使用本地存储,可选 Web 界面绑定到 loopback。应用不会阻止主机网络访问,也不提供沙箱。 +- **维护者响应目标:**48 小时内确认收到,并在 5 个工作日内开始初步分诊;这些是目标,不是 SLA,也不承诺修复期限。 +- **联系方式:**请通过 [SECURITY.md](SECURITY.md) 中说明的私密报告渠道提交安全问题。 --- @@ -441,12 +434,9 @@ python -m compileall -q . -## 17. 德国法定声明(§ 521 BGB) - -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Für unentgeltliche Bereitstellungen gilt gemäß § 521 BGB das gesetzliche Gefälligkeitsrecht: Die Haftung des Anbieters beschränkt sich auf Vorsatz und grobe Fahrlässigkeit. - -本开源软件依据 MIT 许可证免费提供。根据《德国民法典》(BGB)第 521 条,对无偿提供行为的法定责任仅限于故意和重大过失。 +## 17. 法律说明:§ 521 BGB +§ 521 BGB 是否适用于某项具体提供以及会产生何种责任后果,取决于具体情况。本说明不作出此项判断。 --- diff --git a/RELEASE_GATE.md b/RELEASE_GATE.md index e1e9248..5faa90f 100644 --- a/RELEASE_GATE.md +++ b/RELEASE_GATE.md @@ -1,33 +1,51 @@ # Release Gate: llm-note -## Status +## Current gate: version 1.0.5 + +**Status: NOT CLEARED.** The package version remains frozen at 1.0.5. This document does not authorize a version change, tag, release, upload, or publication. + +This gate describes evidence required for a future release from an exact, reviewed candidate commit. On 2026-10-12, the current care worktree passed its local tests, lint, compilation, wheel/sdist build, fresh wheel installation, and artifact-content check. That care-validation snapshot is not a selected release candidate and does not clear this gate. + +| Check | Required evidence | Current state | +|---|---|---| +| Source and CI | Reviewed final diff and successful CI for the exact candidate commit | No release candidate selected; check the current source-CI workflow for a future candidate | +| Tests and lint | Full test suite, Ruff, compilation, and `git diff --check` on the final tree | Care worktree passed 38 tests and all listed checks on 2026-10-12; this does not approve a release candidate | +| Packaging | Build wheel and sdist from the final tree; record hashes; install the wheel in a fresh environment and verify the installed files | Care worktree wheel/sdist built and wheel fresh-installed on 2026-10-12; candidate-specific release review remains required | +| Documentation and metadata | English and translated docs agree on current behavior, dependencies, security response targets, and legal scope | In progress | +| Distribution review | Inspect the produced wheel and sdist contents and metadata; do not infer this from source-only checks | Care worktree artifacts inspected on 2026-10-12; independent review remains required for any future release candidate | + +Local build artifacts are review evidence only. No release artifact is authorized for upload or publication by this gate. + +## Historical gate record: version 1.0.1 (2026-07-15) + +The following record is preserved as historical evidence for the 1.0.1 source at that time. Its UNLOCKED result and checks do not apply to version 1.0.5 or later source. ```text +------------------------------------------+ | | -| STATUS: UNLOCKED | +| HISTORICAL: UNLOCKED | | | +------------------------------------------+ ``` -> **UNLOCKED** = The public repository passed the documented local release gates. +> The 2026-07-15 record states that the public repository passed its then-documented local release gates. It is not a current release approval. -## Checklist +### Historical checklist -| # | Check | Result | Notes | -|---|-------|--------|-------| -| 1 | `.gitignore` with minimum entries | :green_circle: PASS | Present | -| 2 | `README.md` in English | :green_circle: PASS | Present | -| 3 | `LICENSE` (MIT) present | :green_circle: PASS | Present | -| 4 | No `.db` files tracked | :green_circle: PASS | `.gitignore` excludes local DB files | -| 5 | No `.env` files tracked | :green_circle: PASS | `.gitignore` excludes env files | -| 6 | No secrets in tracked files | :green_circle: PASS | Fresh scan completed 2026-07-15 | -| 7 | No hardcoded personal paths | :green_circle: PASS | Fresh scan completed 2026-07-15 | -| 8 | No PII patterns | :green_circle: PASS | No email contacts | -| 9 | No BACH-internal documents | :green_circle: PASS | Provenance only | -| 10 | `TODO.md` with STATUS table | :green_circle: PASS | Present | +| # | Check | Recorded result | Historical note | +|---|-------|---|---| +| 1 | `.gitignore` with minimum entries | PASS | Present | +| 2 | `README.md` in English | PASS | Present | +| 3 | `LICENSE` (MIT) present | PASS | Present | +| 4 | No `.db` files tracked | PASS | `.gitignore` excluded local DB files | +| 5 | No `.env` files tracked | PASS | `.gitignore` excluded environment files | +| 6 | No secrets in tracked files | PASS | Scan recorded 2026-07-15 | +| 7 | No hardcoded personal paths | PASS | Scan recorded 2026-07-15 | +| 8 | PII patterns | PASS recorded | The old note “No email contacts” was incomplete; public repository files contain contact email addresses. This is not a comprehensive PII finding. | +| 9 | No BACH-internal documents | PASS | Provenance only | +| 10 | `TODO.md` with status table | PASS | Present | -## Gate Check Execution +### Historical gate execution ```text Date: 2026-07-15 @@ -37,9 +55,9 @@ Exit Code: 0 Output: 10 PASS, 0 FAIL, 0 WARN ``` -## Verification +### Historical verification -| Check | Result | +| Check | Recorded result | |---|---| | Independent final review | 0×P0, 0×P1, 0×P2 | | Pytest | 16 passed | @@ -47,25 +65,24 @@ Output: 10 PASS, 0 FAIL, 0 WARN | Bandit | Product package clean | | Windows multi-process transfer probe | 12/12 rounds passed | | Forced transfer failure windows | Target, partial multi-target, and final source retries passed | -| Package build | Wheel and sdist 1.0.1 built from the final source | +| Package build | Wheel and sdist 1.0.1 built from the then-current source | | Fresh wheel install | `pip check` clean; 11/11 package files source-identical | | Module manifest | v2 schema valid; public Git source configured | -Artifacts: +Historical artifact names: ```text llm_note-1.0.1-py3-none-any.whl llm_note-1.0.1.tar.gz ``` -Final SHA-256 values are recorded in the external FABLE run log after the -source documentation is frozen and the artifacts are rebuilt. +The historical record said final SHA-256 values were recorded in an external FABLE run log after the source documentation was frozen and artifacts rebuilt. -## Sign-Off +### Historical sign-off | Field | Value | -|-------|-------| +|---|---| | Responsible | Lukas Geiger (@lukisch) | -| Review Date | 2026-07-15 | +| Review date | 2026-07-15 | | Decision | UNLOCKED after exit code 0 | -| Remarks | Patch 1.0.1 hardens transfer integrity, Unicode paths, SQLite lifecycle, query bounds, packaging, and CI. | +| Remarks | Patch 1.0.1 addressed transfer integrity, Unicode paths, SQLite lifecycle, query bounds, packaging, and CI. | diff --git a/SECURITY.md b/SECURITY.md index a97ce67..f1c8372 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,71 +7,63 @@ ## English -### Supported Versions +### Supported versions -| Version | Supported | Security SLA | -| :--- | :---: | :--- | -| 1.0.x | :white_check_mark: | 48h Response / 5-Day Triage | -| < 1.0.0 | :x: | Unsupported | +| Version | Supported | Maintainer response target | +| :--- | :---: | :--- | +| 1.0.x | Yes | Acknowledgement target: 48 hours; initial triage target: 5 business days | +| < 1.0.0 | No | Not supported | -### Reporting a Vulnerability +### Reporting a vulnerability -Please do **not** disclose vulnerabilities via public GitHub issues, discussions, or pull requests. +Please do **not** disclose vulnerabilities through public GitHub issues, discussions, or pull requests. -1. **GitHub Private Vulnerability Reporting (Preferred):** - Navigate to the repository on GitHub, open the **Security** tab, and click **Report a vulnerability**. -2. **Direct Security Contact (Encrypted / Urgent):** - Send an advisory email to: +1. **GitHub Private Vulnerability Reporting (preferred):** Open the repository's **Security** tab and choose **Report a vulnerability**. +2. **Direct security contact:** Email: - `security@open-bricks.org` - CC: `support@lukasgeiger.com`, `lukas@open-bricks.org` -### Response & Remediation SLA +### Maintainer response targets -- **Acknowledgment:** Within **48 hours** of receiving a report. -- **Triage & Severity Assessment:** Within **5 business days**. -- **Fix & Advisory Disclosure:** Coordinated release within 14 calendar days depending on severity. +The maintainer aims to acknowledge a report within 48 hours and begin triage within 5 business days. These are response targets, not a service-level agreement or a guarantee of investigation, a fix, or disclosure by a particular date. There is no fixed remediation deadline. -### Scope & Threat Model +### Scope and current implementation -`llm-note` is intentionally designed local-first and zero-egress: -- **Zero Network Egress:** Core note operations do not communicate with external network services or cloud endpoints. -- **Loopback Interface Binding:** The optional Web GUI binds strictly to `127.0.0.1`. -- **Path Traversal Resistance:** Plain-text notebook storage paths are sanitized to stay within the designated notebook directory. -- **Unprivileged Execution:** Runs strictly in user space (`RunAsInvoker`) and never requires elevated or administrator privileges. +`llm-note` is a local-first notes application. Its core uses local SQLite and plain-text notebook files, and the project declares no additional Python runtime packages. ---- +- The optional web interface binds to loopback at `127.0.0.1`. This is not authentication against other processes running as the same user. +- Notebook paths are validated and kept within the configured notebook root by the application. +- The process does not request administrative or root elevation and inherits the permissions of the process that launches it. +- The application does not provide an operating-system egress block, sandbox, or privilege drop. Network access depends on the host environment; no zero-egress guarantee is made. ## Deutsch ### Unterstützte Versionen -| Version | Unterstützt | Sicherheits-SLA | -| :--- | :---: | :--- | -| 1.0.x | :white_check_mark: | 48h Antwort / 5 Tage Triage | -| < 1.0.0 | :x: | Nicht unterstützt | +| Version | Unterstützt | Reaktionsziel des Maintainers | +| :--- | :---: | :--- | +| 1.0.x | Ja | Eingangsbestätigung: 48 Stunden; Beginn der Triage: 5 Werktage | +| < 1.0.0 | Nein | Nicht unterstützt | -### Melden einer Schwachstelle +### Schwachstellen melden -Bitte veröffentliche Sicherheitslücken **nicht** in öffentlichen Issues oder Foren. +Veröffentliche Sicherheitslücken **nicht** in öffentlichen GitHub-Issues, Diskussionen oder Pull Requests. -1. **GitHub Private Vulnerability Reporting (Bevorzugt):** - Öffne das Repository auf GitHub, wähle den Reiter **Security** und klicke auf **Report a vulnerability**. -2. **Direkter Sicherheitskontakt:** - Sende eine E-Mail an: +1. **GitHub Private Vulnerability Reporting (bevorzugt):** Öffne im Repository den Reiter **Security** und wähle **Report a vulnerability**. +2. **Direkter Sicherheitskontakt:** Schreibe an: - `security@open-bricks.org` - CC: `support@lukasgeiger.com`, `lukas@open-bricks.org` -### Reaktions- und Behebungs-SLA +### Reaktionsziele des Maintainers + +Der Maintainer strebt an, innerhalb von 48 Stunden den Eingang zu bestätigen und innerhalb von 5 Werktagen mit der Triage zu beginnen. Das sind Reaktionsziele, keine Service-Level-Vereinbarung und keine Garantie für Untersuchung, Korrektur oder Veröffentlichung bis zu einem bestimmten Datum. Eine feste Frist für Korrekturen gibt es nicht. -- **Eingangsbestätigung:** Innerhalb von **48 Stunden**. -- **Triage & Risikobewertung:** Innerhalb von **5 Werktagen**. -- **Patch & Veröffentlichung:** Koordinierter Release innerhalb von 14 Kalendertagen. +### Geltungsbereich und aktueller Implementierungsstand -### Geltungsbereich & Sicherheitsmodell +`llm-note` ist eine lokal ausgerichtete Notizanwendung. Der Kern verwendet lokale SQLite-Datenbanken und Klartext-Notizbücher; das Projekt deklariert keine zusätzlichen Python-Laufzeitpakete. -`llm-note` arbeitet lokal und ohne ausgehenden Netzwerkverkehr: -- **Keine Netzwerk-Telemetrie:** Der Notizkern führt keine externen Netzwerkverbindungen aus. -- **Loopback-Bindung:** Die optionale Web-GUI lauscht ausschließlich auf `127.0.0.1`. -- **Schutz vor Pfad-Traversal:** Notizbuch-Pfade werden validiert und auf das Zielverzeichnis begrenzt. -- **Keine Rechteausweitung:** Führt Code ausschließlich mit Standard-Benutzerrechten aus (`RunAsInvoker`). +- Die optionale Weboberfläche bindet an die Loopback-Adresse `127.0.0.1`. Das ist keine Authentifizierung gegenüber anderen Prozessen desselben Benutzers. +- Die Anwendung validiert Notizbuchpfade und hält sie innerhalb des konfigurierten Notizbuch-Stammverzeichnisses. +- Der Prozess fordert keine Administrator- oder Root-Erhöhung an und übernimmt die Berechtigungen des aufrufenden Prozesses. +- Die Anwendung stellt keine Egress-Sperre des Betriebssystems, keine Sandbox und keinen Rechteentzug bereit. Der Netzwerkzugriff hängt von der Hostumgebung ab; eine Zero-Egress-Garantie wird nicht gegeben. diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 5a9769d..279ecfb 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -1,98 +1,36 @@ -# Third-Party License Audit & Transparency Notice +# Third-party dependency and license notes -## 1. Executive Summary & Zero External Runtime Dependencies +Reviewed: 2026-10-12 -`llm-note` is engineered with an uncompromising **zero external runtime dependencies** architectural mandate. The package relies exclusively on the Python standard library for all runtime features: SQLite thought persistence, plain-text file notebook coordination, the CLI, the multi-locale translation engine, and the loopback-only web GUI (Denkarium). +This document summarizes direct Python dependencies declared or used by this repository. It is a scoped dependency note, not a complete software bill of materials, a transitive dependency audit, a license-compliance opinion, or a security certification. The MIT license for this repository is in [LICENSE](LICENSE). -```text -=============================================================================== - llm-note RUNTIME DEPENDENCY AUDIT -=============================================================================== -Runtime Dependencies: 0 (Zero) -External Network Egress: 0 (Zero / Air-Gapped) -Elevated Privileges Needed: 0 (RunAsInvoker unprivileged user space) -License Architecture: 100% Permissive (MIT / Python Software Foundation) -Copyleft Obligations: None (Zero GPL, LGPL, AGPL, SSPL) -=============================================================================== -``` +## Runtime ---- +The `[project]` metadata in `pyproject.toml` declares no Python runtime package dependencies. The application uses modules from the Python standard library, including `sqlite3`, `http.server`, and `argparse`. SQLite and other native components are supplied by the Python and operating-system environment. -## 2. Software Bill of Materials (SBOM) +This statement describes the project metadata and direct runtime package requirements. It does not inventory every component in a user's Python distribution or make a claim about all possible distribution contents. -### 2.1 Core Runtime Components (Python Standard Library) +## Build, test, and lint tools -All core modules are governed by the official [Python Software Foundation License](https://docs.python.org/3/license.html), which is OSI-approved and fully compatible with the permissive MIT License. - -| Standard Library Module | Purpose in `llm-note` | Upstream Governance | SPDX License ID | +| Tool | Repository use | Declared or invoked by | Upstream license information | | :--- | :--- | :--- | :--- | -| `sqlite3` | Local ACID thought log & metadata storage | Python Software Foundation | `PSF-2.0` | -| `http.server` | Local loopback GUI server (`127.0.0.1`) | Python Software Foundation | `PSF-2.0` | -| `urllib.parse` | Query string & URL parsing for GUI endpoints | Python Software Foundation | `PSF-2.0` | -| `argparse` | Command-line interface parsing (`llm-note`) | Python Software Foundation | `PSF-2.0` | -| `json` | Structured API serialization & locale file parsing | Python Software Foundation | `PSF-2.0` | -| `pathlib` | Cross-platform filesystem path abstraction | Python Software Foundation | `PSF-2.0` | -| `threading` | GUI loopback server process control | Python Software Foundation | `PSF-2.0` | -| `dataclasses` | Strongly typed entry structures | Python Software Foundation | `PSF-2.0` | -| `datetime` | ISO-8601 UTC timestamp generation | Python Software Foundation | `PSF-2.0` | -| `hashlib` | Idempotent transfer marker identification | Python Software Foundation | `PSF-2.0` | -| `os`, `sys`, `re` | Path safety, encoding, regex literal searches | Python Software Foundation | `PSF-2.0` | - -### 2.2 Development, Testing & Build-Time Tooling (Not Distributed at Runtime) - -The following tools are utilized exclusively during development, linting, packaging, and CI testing. They are **not** bundled into the distribution wheel and are **not** required for running `llm-note`. - -| Tool | Purpose | License | SPDX License ID | Copyleft? | -| :--- | :--- | :--- | :--- | :---: | -| `hatchling` | PEP 517/621 build backend | MIT License | `MIT` | No | -| `pytest` | Test execution framework | MIT License | `MIT` | No | -| `ruff` | Fast Python linter & code formatter | MIT / Apache-2.0 | `MIT OR Apache-2.0` | No | - ---- - -## 3. Governance & System Invariants - -The implementation of `llm-note` complies strictly with the following 10 architectural invariants: - -| Invariant ID | Name | Architectural Contract & Guarantee | -| :--- | :--- | :--- | -| `INV-LOCAL-01` | **100% Local-First & Zero Egress** | Never initiates outbound network connections. No telemetry, no remote analytics, no API pingbacks. | -| `INV-LOCAL-02` | **SQLite Single-File Storage** | All structured agent notes are stored in a standard SQLite file (`data/notes.db`) with full transactional integrity. | -| `INV-LOCAL-03` | **Plain-Text Notebook Inboxes** | Plain-text scratchpad files (`notebooks/*.txt`) enable effortless Git tracking and human-in-the-loop editing. | -| `INV-LOCAL-04` | **Standard Library Only** | Zero third-party runtime dependencies. Installs cleanly anywhere Python 3.10+ is available without wheel downloads. | -| `INV-LOCAL-05` | **Crash-Safe Atomic Transfers** | Safe cross-process coordination via `.llm-note.lock` and `#LLM-NOTE-ID` idempotency markers preventing note duplication. | -| `INV-LOCAL-06` | **Loopback-Bound Web GUI** | Optional Denkarium GUI strictly binds to loopback (`127.0.0.1`), with support for custom ports and `--no-browser`. | -| `INV-LOCAL-07` | **Multi-Locale I18N** | Native message bundling across 6 languages: English, German, Spanish, Simplified Chinese, Japanese, and Russian. | -| `INV-LOCAL-08` | **RunAsInvoker Execution** | Fully operational in unprivileged user space. Zero administrative elevation, no kernel hooks, no driver installation. | -| `INV-LOCAL-09` | **Agent Skill Packaging** | Ships an agent-ready skill definition (`skills/llm-note/SKILL.md`) for seamless LLM workflow tool integration. | -| `INV-LOCAL-10` | **48-Hour Security SLA** | Formal vulnerability handling commitments documented in `SECURITY.md` (48h triage, 5d response). | - ---- - -## 4. Zero-Copyleft & IP Affirmation - -1. **No Copyleft Taint**: No code from GNU General Public License (GPL v2/v3), GNU Affero General Public License (AGPL), or Server Side Public License (SSPL) is included, linked, or vendored within `llm-note`. -2. **Commercial & Private Use**: The permissive MIT License grants users the unrestricted right to inspect, modify, distribute, embed, and utilize `llm-note` in private, commercial, and enterprise software ecosystems without royalty obligations. -3. **BACH Extraction Provenance**: The package was cleanly decoupled from the BACH desktop assistant codebase (specifically Notizblock and Denkarium). All historical ties and proprietary abstractions were refactored into pure standard-library interfaces. - ---- - -## 5. Security & Privilege Notice (`RunAsInvoker`) - -`llm-note` requires no administrator rights, root privileges, or Windows UAC elevation. Running `llm-note` under elevated privileges is neither recommended nor supported. +| `hatchling>=1.25` | PEP 517 build backend | `pyproject.toml` `[build-system]` | MIT; [PyPA Hatch source](https://github.com/pypa/hatch/blob/master/LICENSE.txt) | +| `pytest` | Test runner | CI workflow and contributor checks | MIT; [pytest source](https://github.com/pytest-dev/pytest/blob/main/LICENSE) | +| `ruff` | Linter | CI workflow and contributor checks | MIT; [Ruff source](https://github.com/astral-sh/ruff/blob/main/LICENSE) | +| `build` | Local wheel and source-distribution builder | CI workflow and contributor checks | MIT; [PyPA build source](https://github.com/pypa/build/blob/main/LICENSE) | -- **Filesystem Boundaries**: All database writes and notebook file operations are strictly confined to the directory paths provided by the user or configuration. Path traversal attempts (e.g. `../`) are rejected during path resolution. -- **Process Isolation**: The loopback HTTP server runs in the calling process thread, handles requests synchronously, and terminates cleanly upon receiving `SIGINT` or `Ctrl+C`. +These are build or development tools, not application runtime dependencies. Their versions and transitive dependencies are managed by the environment that installs them and are not exhaustively inventoried here. License links point to the respective upstream projects; this note does not certify the complete licensing status of their dependency trees. ---- +## Standard library reference -## 6. Plain-Text Companion & Audit Affirmation +The Python standard library's licensing information is maintained by the [Python Software Foundation](https://docs.python.org/3/license.html). This repository does not vendor a separate copy of the Python runtime. -A standardized plain-text companion file `THIRD_PARTY_LICENSES.txt` is maintained in the repository root for automated packaging, package distribution, and offline inspection. +## Implementation facts -- **Last Re-Audit Date**: 2026-10-11 -- **Auditor**: Antigravity / Gemini 3.8 Flash High (Pfad A Repository-Hygiene & CI-Matrix-Härtung) -- **Status**: 100% Verified Compliant (0 External Runtime Dependencies, INV-LOCAL-01..INV-SLA-10) +- Notes are stored in local SQLite and plain-text notebook files. +- The optional web interface binds to loopback at `127.0.0.1`. +- The process does not request administrative elevation and inherits the permissions of the process that launches it. +- These implementation facts do not establish an operating-system egress block, sandbox, complete software inventory, or independent security certification. diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index 9a23f8a..703708e 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -1,81 +1,46 @@ -THIRD-PARTY LICENSES & LEVEL 1 SBOM NOTICE +THIRD-PARTY DEPENDENCY NOTES Project: doc-bricks/llm-note -Audited: 2026-10-11 -Repository License: MIT License (see LICENSE) -Repository Attribution Notice: NOTICE (see NOTICE) -Architecture & Security: 100% Local-First, Zero-Egress, Unprivileged User-Mode (RunAsInvoker), Zero External Runtime Dependencies, Invariant Cross-Reference Matrix (INV-LOCAL-01..INV-SLA-10) - -================================================================================ -1. EXECUTIVE SUMMARY & ZERO-COPYLEFT ISOLATION GUARANTEE -================================================================================ - -llm-note is a local-first note and notebook engine engineered with an uncompromising -zero external runtime dependencies architecture. It operates exclusively on local SQLite -databases and plain-text files. - -- 100% Permissive Dependencies: Core execution relies solely on the Python Standard - Library (PSF-2.0) and SQLite. -- Zero-Copyleft Isolation Guarantee: No GPL, AGPL, SSPL, or copyleft-encumbered - libraries are bundled, linked, or distributed at runtime. -- Unprivileged User-Mode (RunAsInvoker): llm-note executes exclusively in standard, - non-elevated user space without requesting administrative or root privileges. -- Zero Egress: Strictly zero outbound network connections, zero analytics, and zero telemetry. - -================================================================================ -2. INVARIANT CROSS-REFERENCE MATRIX (INV-LOCAL-01 .. INV-SLA-10) -================================================================================ - -Invariant ID | Operational Mandate | Technical Enforcement | License Scope ----------------+------------------------------------+--------------------------------------+------------------- -INV-LOCAL-01 | 100% Local-First & Zero Egress | Zero outbound telemetry or egress | MIT / PSF-2.0 -INV-LOCAL-02 | SQLite Single-File Storage | Local ACID store at data/notes.db | MIT / PSF-2.0 -INV-LOCAL-03 | Plain-Text Notebook Inboxes | Plain-text scratchpads in notebooks/ | MIT / PSF-2.0 -INV-LOCAL-04 | Standard Library Only | Zero 3rd-party runtime packages | MIT / PSF-2.0 -INV-LOCAL-05 | Crash-Safe Atomic Transfers | Process lock & idempotency markers | MIT / PSF-2.0 -INV-LOCAL-06 | Loopback-Bound Web GUI | Binds strictly to 127.0.0.1 | MIT / PSF-2.0 -INV-LOCAL-07 | Multi-Locale I18N | Native bundled translations (6 lang) | MIT / PSF-2.0 -INV-LOCAL-08 | RunAsInvoker Execution | Non-elevated user space execution | MIT / PSF-2.0 -INV-LOCAL-09 | Agent Skill Packaging | Bundled standalone agent skill | MIT / PSF-2.0 -INV-LOCAL-10 | 48-Hour Security Response SLA | Documented SLA in SECURITY.md | SECURITY.md - -================================================================================ -3. RUNTIME SOFTWARE BILL OF MATERIALS (SBOM) -================================================================================ - -Component Version/Release SPDX License ID Upstream Authority ------------------------------- --------------- --------------- -------------------------- -Python Standard Library (Core) 3.10 - 3.13 PSF-2.0 Python Software Foundation - - sqlite3 PSF-2.0 Python Software Foundation - - http.server PSF-2.0 Python Software Foundation - - urllib.parse PSF-2.0 Python Software Foundation - - argparse PSF-2.0 Python Software Foundation - - json PSF-2.0 Python Software Foundation - - pathlib PSF-2.0 Python Software Foundation - - threading PSF-2.0 Python Software Foundation - - dataclasses PSF-2.0 Python Software Foundation - - hashlib PSF-2.0 Python Software Foundation - - datetime, os, sys, re PSF-2.0 Python Software Foundation - -Development, Linting & Build Tools (Not Distributed at Runtime): - - hatchling MIT Hatchling Team - - pytest MIT pytest-dev Team - - ruff MIT / Apache-2.0 Astral Software Inc. - -================================================================================ -4. GERMAN STATUTORY NOTICE (§ 521 BGB GEFÄLLIGKEITSRECHT) -================================================================================ - -Dieses Open-Source-Projekt wird unentgeltlich zur Verfügung gestellt. Gemäß § 521 BGB -haftet der Entwickler im Gefälligkeitsverhältnis nur für Vorsatz und grobe Fahrlässigkeit. -Jegliche weitergehende Haftung oder Gewährleistung für mittelbare oder unmittelbare Schäden, -Datenverluste oder Betriebsunterbrechungen ist im gesetzlich zulässigen Rahmen ausgeschlossen. - -================================================================================ -5. SECURITY & INCIDENT RESPONSE SLA -================================================================================ - -Sicherheitsrelevante Schwachstellen und vertrauliche Meldungen werden nach den in -SECURITY.md garantierten Service Level Agreements bearbeitet: -- Erste Bestätigung & Triage: innerhalb von 48 Stunden -- Statusupdate & Patch-Plan: innerhalb von 5 Tagen -- Bereitstellung von Korrekturen: via GitHub Advisory / Pull Request +Reviewed: 2026-10-12 +Repository license: MIT (see LICENSE) + +Scope +----- +This note summarizes direct Python dependencies declared by the repository. It is +not a complete software bill of materials, a review of every transitive build or +test dependency, or a legal or security certification. Distribution contents and +environment-provided components may require separate inspection. + +Runtime +------- +The current project metadata declares no additional Python runtime packages. +The application uses the Python standard library and SQLite supplied by the +Python runtime. No third-party Python runtime dependency is listed in +pyproject.toml. + +Build and development +--------------------- +The build-system declaration in pyproject.toml requires hatchling>=1.25. +Test and lint tools are used in the development/CI context; they are not +application runtime dependencies. Their complete transitive dependency and +license inventory is outside the scope of this note. + +Repository facts +---------------- +- The application stores notes in local SQLite and plain-text notebook files. +- The optional web interface binds to loopback. +- The process does not require administrative elevation and inherits the + permissions of the process that launches it. +- These facts do not establish an operating-system egress block, sandbox, + complete dependency inventory, or independent security certification. + +Legal information +----------------- +This document is not legal advice and does not determine how liability rules +apply to a particular user or distribution. Section 521 BGB may be relevant +depending on the specific facts; no conclusion about its applicability or +effect is made here. The repository's MIT license remains in LICENSE. + +Security response +----------------- +See SECURITY.md for the current maintainer response targets. Acknowledgement +and triage targets are not guaranteed fix or disclosure deadlines. diff --git a/llm_note/cli.py b/llm_note/cli.py index ead2109..8d3c1f3 100644 --- a/llm_note/cli.py +++ b/llm_note/cli.py @@ -3,74 +3,269 @@ from __future__ import annotations import argparse +import re +import sys +from functools import partial -from .i18n import load_messages +from .i18n import load_messages, normalize_locale from .store import MAX_QUERY_LIMIT, NoteStore -def _query_limit(value: str) -> int: +class LocalizedArgumentParser(argparse.ArgumentParser): + """Argument parser whose generated help and errors use one locale.""" + + def __init__(self, *args, messages: dict[str, str], **kwargs) -> None: + self.messages = messages + kwargs["add_help"] = False + super().__init__(*args, **kwargs) + self.add_argument( + "-h", + "--help", + action="help", + help=self.messages["cli_help_action"], + ) + + def format_usage(self) -> str: + return self._localize_help(super().format_usage()) + + def format_help(self) -> str: + return self._localize_help(super().format_help()) + + def error(self, message: str) -> None: + self.print_usage(sys.stderr) + translated = self._localize_error(message) + self.exit( + 2, + f"{self.prog}: {self.messages['cli_error_label']}: {translated}\n", + ) + + def _localize_help(self, text: str) -> str: + for source, key in ( + ("usage:", "cli_usage_label"), + ("positional arguments:", "cli_positional_label"), + ("options:", "cli_options_label"), + ): + text = text.replace(source, f"{self.messages[key]}:") + text = text.replace( + "show this help message and exit", + self.messages["cli_help_action"], + ) + return text + + def _localize_error(self, message: str) -> str: + required = "the following arguments are required: " + if message.startswith(required): + arguments = message[len(required) :] + return self.messages["cli_required_arguments"].format( + arguments=arguments + ) + + unrecognized = "unrecognized arguments: " + if message.startswith(unrecognized): + arguments = message[len(unrecognized) :] + return self.messages["cli_unrecognized_arguments"].format( + arguments=arguments + ) + + if message.startswith("argument ") and ": " in message: + argument, detail = message[len("argument ") :].split(": ", maxsplit=1) + detail = self._localize_error_detail(detail) + return self.messages["cli_argument_error"].format( + argument=argument, + message=detail, + ) + return self._localize_error_detail(message) + + def _localize_error_detail(self, message: str) -> str: + if message == "expected one argument": + return self.messages["cli_expected_one_argument"] + + invalid_integer = "invalid int value: " + if message.startswith(invalid_integer): + value = message[len(invalid_integer) :] + return self.messages["cli_invalid_integer"].format(value=value) + + match = re.fullmatch(r"invalid choice: (.+?) \(choose from (.+)\)", message) + if match: + return self.messages["cli_invalid_choice"].format( + value=match.group(1), + choices=match.group(2), + ) + return message + + +def _query_limit(value: str, messages: dict[str, str]) -> int: try: limit = int(value) except ValueError as exc: - raise argparse.ArgumentTypeError("limit must be an integer") from exc + raise argparse.ArgumentTypeError(messages["cli_limit_integer"]) from exc if not 0 <= limit <= MAX_QUERY_LIMIT: raise argparse.ArgumentTypeError( - f"limit must be between 0 and {MAX_QUERY_LIMIT}" + messages["cli_limit_range"].format(max=MAX_QUERY_LIMIT) ) return limit -def _port(value: str) -> int: +def _port(value: str, messages: dict[str, str]) -> int: try: port = int(value) except ValueError as exc: - raise argparse.ArgumentTypeError("port must be an integer") from exc + raise argparse.ArgumentTypeError(messages["cli_port_integer"]) from exc if not 0 <= port <= 65535: - raise argparse.ArgumentTypeError("port must be between 0 and 65535") + raise argparse.ArgumentTypeError(messages["cli_port_range"]) return port -def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser( - prog="llm-note", description="Local-first notes for LLM agents" +def _mood(value: str, messages: dict[str, str]) -> int: + try: + return int(value) + except ValueError as exc: + raise argparse.ArgumentTypeError(messages["cli_mood_integer"]) from exc + + +def build_parser(locale: str | None = "en") -> argparse.ArgumentParser: + messages = load_messages(locale) + + def parser_factory(**kwargs): + return LocalizedArgumentParser(messages=messages, **kwargs) + + parser = LocalizedArgumentParser( + prog="llm-note", + description=messages["cli_description"], + messages=messages, + ) + parser.add_argument("--db", default="llm-note.db", help=messages["cli_db_help"]) + parser.add_argument( + "--locale", + default=None, + metavar="LOCALE", + help=messages["cli_locale_help"], + ) + sub = parser.add_subparsers( + dest="command", + required=True, + parser_class=parser_factory, ) - parser.add_argument("--db", default="llm-note.db", help="SQLite database path") - parser.add_argument("--locale", default="en", help="Message locale") - sub = parser.add_subparsers(dest="command", required=True) - write = sub.add_parser("write", help="Write a note") - write.add_argument("content") - write.add_argument("--type", default="note", dest="entry_type") - write.add_argument("--cat", default="note", dest="category") - write.add_argument("--title") - write.add_argument("--mood", type=int) + write = sub.add_parser( + "write", + help=messages["cli_write_help"], + description=messages["cli_write_help"], + ) + write.add_argument("content", help=messages["cli_content_help"]) + write.add_argument( + "--type", + default="note", + dest="entry_type", + help=messages["cli_type_help"], + ) + write.add_argument( + "--cat", + default="note", + dest="category", + help=messages["cli_category_help"], + ) + write.add_argument("--title", help=messages["cli_title_help"]) + write.add_argument( + "--mood", + type=partial(_mood, messages=messages), + help=messages["cli_mood_help"], + ) - read = sub.add_parser("read", help="Read recent notes") - read.add_argument("--type", dest="entry_type") - read.add_argument("--cat", dest="category") - read.add_argument("--limit", type=_query_limit, default=10) + read = sub.add_parser( + "read", + help=messages["cli_read_help"], + description=messages["cli_read_help"], + ) + read.add_argument( + "--type", + dest="entry_type", + help=messages["cli_type_help"], + ) + read.add_argument( + "--cat", + dest="category", + help=messages["cli_category_help"], + ) + read.add_argument( + "--limit", + type=partial(_query_limit, messages=messages), + default=10, + help=messages["cli_limit_help"], + ) - search = sub.add_parser("search", help="Search notes") - search.add_argument("term") + search = sub.add_parser( + "search", + help=messages["cli_search_help"], + description=messages["cli_search_help"], + ) + search.add_argument("term", help=messages["cli_term_help"]) - brainstorm = sub.add_parser("brainstorm", help="Create a brainstorm note") - brainstorm.add_argument("topic") + brainstorm = sub.add_parser( + "brainstorm", + help=messages["cli_brainstorm_help"], + description=messages["cli_brainstorm_help"], + ) + brainstorm.add_argument("topic", help=messages["cli_topic_help"]) - sub.add_parser("stats", help="Show statistics") + sub.add_parser( + "stats", + help=messages["cli_stats_help"], + description=messages["cli_stats_help"], + ) - gui = sub.add_parser("gui", help="Open the local web interface") - gui.add_argument("--port", type=_port, default=8000) + gui = sub.add_parser( + "gui", + help=messages["cli_gui_help"], + description=messages["cli_gui_help"], + ) + gui.add_argument( + "--port", + type=partial(_port, messages=messages), + default=8000, + help=messages["cli_port_help"], + ) gui.add_argument( "--no-browser", action="store_true", - help="Start the server without opening a browser", + help=messages["cli_no_browser_help"], ) return parser +def _requested_locale(argv: list[str]) -> str | None: + locale: str | None = None + commands = {"write", "read", "search", "brainstorm", "stats", "gui"} + index = 0 + while index < len(argv): + argument = argv[index] + if argument == "--": + break + if argument in commands: + break + if argument == "--db": + index += 2 + continue + if argument.startswith("--db="): + index += 1 + continue + if argument.startswith("--locale="): + locale = argument.split("=", maxsplit=1)[1] + index += 1 + continue + if argument == "--locale" and index + 1 < len(argv): + locale = argv[index + 1] + index += 2 + continue + index += 1 + return locale + + def main(argv: list[str] | None = None) -> int: - parser = build_parser() - args = parser.parse_args(argv) + arguments = list(sys.argv[1:] if argv is None else argv) + messages_locale = normalize_locale(_requested_locale(arguments)) + parser = build_parser(messages_locale) + args = parser.parse_args(arguments) if args.command == "gui": from .gui import run_server diff --git a/llm_note/gui.py b/llm_note/gui.py index 5f56a45..bf449c1 100644 --- a/llm_note/gui.py +++ b/llm_note/gui.py @@ -13,55 +13,11 @@ from typing import Any from urllib.parse import parse_qs, urlsplit -from .i18n import STANDARD_LOCALES +from .i18n import STANDARD_LOCALES, load_messages, normalize_locale from .store import MAX_QUERY_LIMIT, NoteStore MAX_REQUEST_BYTES = 1_000_000 -_GUI_COPY = { - "en": { - "document_title": "llm-note Denkarium", - "heading": "Denkarium", - "subtitle": "Notes · logbook · ideas", - "compose_placeholder": "What is on your mind?", - "note": "Note", - "notes": "Notes", - "logbook": "Logbook", - "category": "Category", - "optional_title": "Title (optional)", - "mood": "Mood", - "save": "Save", - "search": "Search notes …", - "all": "All", - "entries": "entries", - "empty_title": "Empty pages", - "empty_body": "Write your first note.", - "loading": "Loading …", - "load_error": "Could not load notes.", - "save_error": "Could not save the note.", - }, - "de": { - "document_title": "llm-note Denkarium", - "heading": "Denkarium", - "subtitle": "Notizen · Logbuch · Ideen", - "compose_placeholder": "Was bewegt dich gerade?", - "note": "Notiz", - "notes": "Notizen", - "logbook": "Logbuch", - "category": "Kategorie", - "optional_title": "Titel (optional)", - "mood": "Stimmung", - "save": "Speichern", - "search": "Notizen durchsuchen …", - "all": "Alle", - "entries": "Einträge", - "empty_title": "Leere Seiten", - "empty_body": "Schreibe deine erste Notiz.", - "loading": "Lädt …", - "load_error": "Notizen konnten nicht geladen werden.", - "save_error": "Notiz konnte nicht gespeichert werden.", - }, -} class NoteHTTPServer(ThreadingHTTPServer): @@ -74,10 +30,11 @@ def __init__( self, server_address: tuple[str, int], store: NoteStore, - locale: str, + locale: str | None, ) -> None: self.store = store - self.locale = locale if locale in STANDARD_LOCALES else "en" + # The immutable launch value seeds each browser; selections stay client-local. + self.locale = normalize_locale(locale) if locale is not None else None super().__init__(server_address, NoteRequestHandler) @@ -240,12 +197,24 @@ def _render_page(self) -> str: .joinpath("templates", "denkarium.html") .read_text(encoding="utf-8") ) - locale = self.server.locale if self.server.locale in _GUI_COPY else "en" - copy_json = json.dumps(_GUI_COPY[locale], ensure_ascii=False).replace( - " NoteHTTPServer: """Create a loopback-only GUI server without starting its event loop.""" @@ -297,15 +266,16 @@ def run_server( db_path: str | Path = "llm-note.db", *, port: int = 8000, - locale: str = "en", + locale: str | None = None, open_browser: bool = True, ) -> None: """Run the local GUI until interrupted.""" server = create_server(db_path, port=port, locale=locale) + messages = load_messages(locale) url = f"http://127.0.0.1:{server.server_port}/" - print(f"llm-note GUI: {url}") - print("Press Ctrl+C to stop.") + print(messages["cli_gui_started"].format(url=url)) + print(messages["cli_gui_stop"]) if open_browser: threading.Timer(0.2, webbrowser.open, args=(url,)).start() try: diff --git a/llm_note/i18n.py b/llm_note/i18n.py index ba35c06..8f976d9 100644 --- a/llm_note/i18n.py +++ b/llm_note/i18n.py @@ -8,9 +8,27 @@ STANDARD_LOCALES = ("de", "en", "es", "zh-Hans", "ja", "ru") -def load_messages(locale: str = "en") -> dict[str, str]: - if locale not in STANDARD_LOCALES: - locale = "en" +def normalize_locale(locale: str | None = None) -> str: + """Return a supported catalog for a language or regional locale tag.""" + if not isinstance(locale, str) or not locale.strip(): + return "en" + + tag = locale.strip().replace("_", "-") + for supported in STANDARD_LOCALES: + if tag.casefold() == supported.casefold(): + return supported + + language = tag.split("-", maxsplit=1)[0].casefold() + if language == "zh": + return "zh-Hans" + for supported in STANDARD_LOCALES: + if language == supported.casefold(): + return supported + return "en" + + +def load_messages(locale: str | None = "en") -> dict[str, str]: + locale = normalize_locale(locale) with resources.files("llm_note.locales").joinpath(f"{locale}.json").open( "r", encoding="utf-8" ) as handle: diff --git a/llm_note/locales/de.json b/llm_note/locales/de.json index cd82367..db5c3b9 100644 --- a/llm_note/locales/de.json +++ b/llm_note/locales/de.json @@ -2,5 +2,72 @@ "saved": "Notiz #{id} gespeichert ({category})", "no_results": "keine Notizen gefunden", "brainstorm_saved": "Brainstorm-Notiz #{id} erstellt", - "stats_total": "Notizen: {total}; befördert: {promoted}" + "stats_total": "Notizen: {total}; befördert: {promoted}", + "gui_document_title": "llm-note Denkarium", + "gui_heading": "Denkarium", + "gui_subtitle": "Notizen · Logbuch · Ideen", + "gui_compose_placeholder": "Was bewegt dich gerade?", + "gui_note": "Notiz", + "gui_notes": "Notizen", + "gui_logbook": "Logbuch", + "gui_category": "Kategorie", + "gui_optional_title": "Titel (optional)", + "gui_mood": "Stimmung", + "gui_save": "Speichern", + "gui_search": "Notizen durchsuchen …", + "gui_all": "Alle", + "gui_entries": "Einträge", + "gui_empty_title": "Leere Seiten", + "gui_empty_body": "Schreibe deine erste Notiz.", + "gui_loading": "Lädt …", + "gui_load_error": "Notizen konnten nicht geladen werden.", + "gui_save_error": "Notiz konnte nicht gespeichert werden.", + "gui_language": "Sprache", + "gui_settings": "Anzeigeeinstellungen", + "gui_filters": "Notizfilter", + "gui_content_label": "Notiztext", + "gui_entry_type_label": "Eintragstyp", + "gui_category_label": "Kategorie", + "gui_title_label": "Titel", + "gui_mood_label": "Stimmung", + "gui_font_serif": "Serif", + "gui_font_sans": "Serifenlos", + "gui_font_mono": "Monospace", + "cli_description": "Lokal gespeicherte Notizen für LLM-Agenten", + "cli_help_action": "diese Hilfe anzeigen und beenden", + "cli_usage_label": "Verwendung", + "cli_positional_label": "Positionsargumente", + "cli_options_label": "Optionen", + "cli_error_label": "Fehler", + "cli_argument_error": "Argument {argument}: {message}", + "cli_required_arguments": "Diese Argumente sind erforderlich: {arguments}", + "cli_unrecognized_arguments": "Unbekannte Argumente: {arguments}", + "cli_expected_one_argument": "Es wird ein Argument erwartet", + "cli_invalid_integer": "Ungültiger Ganzzahlwert: {value}", + "cli_invalid_choice": "Ungültige Auswahl: {value} (mögliche Werte: {choices})", + "cli_limit_integer": "limit muss eine Ganzzahl sein", + "cli_limit_range": "limit muss zwischen 0 und {max} liegen", + "cli_port_integer": "port muss eine Ganzzahl sein", + "cli_port_range": "port muss zwischen 0 und 65535 liegen", + "cli_mood_integer": "mood muss eine Ganzzahl sein", + "cli_db_help": "Pfad zur SQLite-Datenbank", + "cli_locale_help": "Sprache der Meldungen; für die GUI wird sie als Startsprache gesetzt", + "cli_write_help": "Eine Notiz schreiben", + "cli_read_help": "Aktuelle Notizen lesen", + "cli_search_help": "Notizen durchsuchen", + "cli_brainstorm_help": "Eine Brainstorm-Notiz erstellen", + "cli_stats_help": "Statistik anzeigen", + "cli_gui_help": "Die lokale Weboberfläche öffnen", + "cli_content_help": "Notiztext", + "cli_type_help": "Eintragstyp (Notiz oder Logbuch)", + "cli_category_help": "Kategorie des Eintrags", + "cli_title_help": "Optionaler Titel", + "cli_mood_help": "Stimmungswert von 1 bis 5", + "cli_limit_help": "Maximale Anzahl zu lesender Notizen", + "cli_term_help": "Suchtext", + "cli_topic_help": "Thema für das Brainstorming", + "cli_port_help": "Port des Loopback-Servers", + "cli_no_browser_help": "Server ohne Browserstart ausführen", + "cli_gui_started": "llm-note-Weboberfläche: {url}", + "cli_gui_stop": "Zum Beenden des Servers Ctrl+C drücken." } diff --git a/llm_note/locales/en.json b/llm_note/locales/en.json index e8f158e..dbed255 100644 --- a/llm_note/locales/en.json +++ b/llm_note/locales/en.json @@ -2,5 +2,72 @@ "saved": "saved note #{id} ({category})", "no_results": "no notes found", "brainstorm_saved": "brainstorm note #{id} created", - "stats_total": "notes: {total}; promoted: {promoted}" + "stats_total": "notes: {total}; promoted: {promoted}", + "gui_document_title": "llm-note Denkarium", + "gui_heading": "Denkarium", + "gui_subtitle": "Notes · logbook · ideas", + "gui_compose_placeholder": "What is on your mind?", + "gui_note": "Note", + "gui_notes": "Notes", + "gui_logbook": "Logbook", + "gui_category": "Category", + "gui_optional_title": "Title (optional)", + "gui_mood": "Mood", + "gui_save": "Save", + "gui_search": "Search notes …", + "gui_all": "All", + "gui_entries": "entries", + "gui_empty_title": "Empty pages", + "gui_empty_body": "Write your first note.", + "gui_loading": "Loading …", + "gui_load_error": "Could not load notes.", + "gui_save_error": "Could not save the note.", + "gui_language": "Language", + "gui_settings": "Display settings", + "gui_filters": "Note filters", + "gui_content_label": "Note text", + "gui_entry_type_label": "Entry type", + "gui_category_label": "Category", + "gui_title_label": "Title", + "gui_mood_label": "Mood", + "gui_font_serif": "Serif", + "gui_font_sans": "Sans", + "gui_font_mono": "Mono", + "cli_description": "Local-first notes for LLM agents", + "cli_help_action": "show this help message and exit", + "cli_usage_label": "usage", + "cli_positional_label": "positional arguments", + "cli_options_label": "options", + "cli_error_label": "error", + "cli_argument_error": "argument {argument}: {message}", + "cli_required_arguments": "the following arguments are required: {arguments}", + "cli_unrecognized_arguments": "unrecognized arguments: {arguments}", + "cli_expected_one_argument": "expected one argument", + "cli_invalid_integer": "invalid integer value: {value}", + "cli_invalid_choice": "invalid choice: {value} (choose from {choices})", + "cli_limit_integer": "limit must be an integer", + "cli_limit_range": "limit must be between 0 and {max}", + "cli_port_integer": "port must be an integer", + "cli_port_range": "port must be between 0 and 65535", + "cli_mood_integer": "mood must be an integer", + "cli_db_help": "SQLite database path", + "cli_locale_help": "Message language; for the GUI, sets its initial language", + "cli_write_help": "Write a note", + "cli_read_help": "Read recent notes", + "cli_search_help": "Search notes", + "cli_brainstorm_help": "Create a brainstorm note", + "cli_stats_help": "Show statistics", + "cli_gui_help": "Open the local web interface", + "cli_content_help": "Note text", + "cli_type_help": "Entry type (note or logbook)", + "cli_category_help": "Entry category", + "cli_title_help": "Optional title", + "cli_mood_help": "Mood rating from 1 to 5", + "cli_limit_help": "Maximum number of notes to read", + "cli_term_help": "Text to search for", + "cli_topic_help": "Brainstorm topic", + "cli_port_help": "Loopback server port", + "cli_no_browser_help": "Start the server without opening a browser", + "cli_gui_started": "llm-note GUI: {url}", + "cli_gui_stop": "Press Ctrl+C to stop." } diff --git a/llm_note/locales/es.json b/llm_note/locales/es.json index f27765d..75e7e61 100644 --- a/llm_note/locales/es.json +++ b/llm_note/locales/es.json @@ -2,5 +2,72 @@ "saved": "nota #{id} guardada ({category})", "no_results": "no se encontraron notas", "brainstorm_saved": "nota de lluvia de ideas #{id} creada", - "stats_total": "notas: {total}; promovidas: {promoted}" + "stats_total": "notas: {total}; promovidas: {promoted}", + "gui_document_title": "llm-note Denkarium", + "gui_heading": "Denkarium", + "gui_subtitle": "Notas · diario · ideas", + "gui_compose_placeholder": "¿Qué tienes en mente?", + "gui_note": "Nota", + "gui_notes": "Notas", + "gui_logbook": "Diario", + "gui_category": "Categoría", + "gui_optional_title": "Título (opcional)", + "gui_mood": "Ánimo", + "gui_save": "Guardar", + "gui_search": "Buscar notas …", + "gui_all": "Todo", + "gui_entries": "entradas", + "gui_empty_title": "Páginas vacías", + "gui_empty_body": "Escribe tu primera nota.", + "gui_loading": "Cargando …", + "gui_load_error": "No se pudieron cargar las notas.", + "gui_save_error": "No se pudo guardar la nota.", + "gui_language": "Idioma", + "gui_settings": "Ajustes de visualización", + "gui_filters": "Filtros de notas", + "gui_content_label": "Texto de la nota", + "gui_entry_type_label": "Tipo de entrada", + "gui_category_label": "Categoría", + "gui_title_label": "Título", + "gui_mood_label": "Ánimo", + "gui_font_serif": "Serif", + "gui_font_sans": "Sans", + "gui_font_mono": "Monoespaciada", + "cli_description": "Notas locales para agentes LLM", + "cli_help_action": "mostrar esta ayuda y salir", + "cli_usage_label": "uso", + "cli_positional_label": "argumentos posicionales", + "cli_options_label": "opciones", + "cli_error_label": "error", + "cli_argument_error": "argumento {argument}: {message}", + "cli_required_arguments": "faltan los siguientes argumentos obligatorios: {arguments}", + "cli_unrecognized_arguments": "argumentos no reconocidos: {arguments}", + "cli_expected_one_argument": "se esperaba un argumento", + "cli_invalid_integer": "valor entero no válido: {value}", + "cli_invalid_choice": "opción no válida: {value} (opciones posibles: {choices})", + "cli_limit_integer": "el límite debe ser un entero", + "cli_limit_range": "el límite debe estar entre 0 y {max}", + "cli_port_integer": "el puerto debe ser un entero", + "cli_port_range": "el puerto debe estar entre 0 y 65535", + "cli_mood_integer": "el ánimo debe ser un entero", + "cli_db_help": "Ruta de la base de datos SQLite", + "cli_locale_help": "Idioma de los mensajes; en la GUI establece el idioma inicial", + "cli_write_help": "Escribir una nota", + "cli_read_help": "Leer notas recientes", + "cli_search_help": "Buscar notas", + "cli_brainstorm_help": "Crear una nota de lluvia de ideas", + "cli_stats_help": "Mostrar estadísticas", + "cli_gui_help": "Abrir la interfaz web local", + "cli_content_help": "Texto de la nota", + "cli_type_help": "Tipo de entrada (nota o diario)", + "cli_category_help": "Categoría de la entrada", + "cli_title_help": "Título opcional", + "cli_mood_help": "Valor del ánimo del 1 al 5", + "cli_limit_help": "Número máximo de notas que se leerán", + "cli_term_help": "Texto que se buscará", + "cli_topic_help": "Tema para la lluvia de ideas", + "cli_port_help": "Puerto del servidor de loopback", + "cli_no_browser_help": "Iniciar el servidor sin abrir un navegador", + "cli_gui_started": "Interfaz web local de llm-note: {url}", + "cli_gui_stop": "Pulsa Ctrl+C para detener el servidor." } diff --git a/llm_note/locales/ja.json b/llm_note/locales/ja.json index 8536b40..c22c94c 100644 --- a/llm_note/locales/ja.json +++ b/llm_note/locales/ja.json @@ -2,5 +2,72 @@ "saved": "ノート #{id} を保存しました({category})", "no_results": "ノートが見つかりません", "brainstorm_saved": "ブレインストームノート #{id} を作成しました", - "stats_total": "ノート: {total}; 昇格済み: {promoted}" + "stats_total": "ノート: {total}; 昇格済み: {promoted}", + "gui_document_title": "llm-note Denkarium", + "gui_heading": "Denkarium", + "gui_subtitle": "ノート · ログ · アイデア", + "gui_compose_placeholder": "今、何を考えていますか?", + "gui_note": "ノート", + "gui_notes": "ノート", + "gui_logbook": "ログ", + "gui_category": "カテゴリ", + "gui_optional_title": "タイトル(任意)", + "gui_mood": "気分", + "gui_save": "保存", + "gui_search": "ノートを検索 …", + "gui_all": "すべて", + "gui_entries": "件", + "gui_empty_title": "空白のページ", + "gui_empty_body": "最初のノートを書いてみましょう。", + "gui_loading": "読み込み中 …", + "gui_load_error": "ノートを読み込めませんでした。", + "gui_save_error": "ノートを保存できませんでした。", + "gui_language": "言語", + "gui_settings": "表示設定", + "gui_filters": "ノートの絞り込み", + "gui_content_label": "ノート本文", + "gui_entry_type_label": "記録の種類", + "gui_category_label": "カテゴリ", + "gui_title_label": "タイトル", + "gui_mood_label": "気分", + "gui_font_serif": "セリフ", + "gui_font_sans": "サンセリフ", + "gui_font_mono": "等幅", + "cli_description": "LLM エージェント向けのローカルノート", + "cli_help_action": "このヘルプを表示して終了", + "cli_usage_label": "使い方", + "cli_positional_label": "位置引数", + "cli_options_label": "オプション", + "cli_error_label": "エラー", + "cli_argument_error": "引数 {argument}: {message}", + "cli_required_arguments": "次の引数が必要です: {arguments}", + "cli_unrecognized_arguments": "認識できない引数: {arguments}", + "cli_expected_one_argument": "引数を1つ指定してください", + "cli_invalid_integer": "整数値が無効です: {value}", + "cli_invalid_choice": "選択肢が無効です: {value}(候補: {choices})", + "cli_limit_integer": "limit は整数で指定してください", + "cli_limit_range": "limit は 0 から {max} の範囲で指定してください", + "cli_port_integer": "port は整数で指定してください", + "cli_port_range": "port は 0 から 65535 の範囲で指定してください", + "cli_mood_integer": "mood は整数で指定してください", + "cli_db_help": "SQLite データベースのパス", + "cli_locale_help": "メッセージの言語。GUI では初期表示言語になります", + "cli_write_help": "ノートを書き込む", + "cli_read_help": "最近のノートを読む", + "cli_search_help": "ノートを検索する", + "cli_brainstorm_help": "ブレインストーミングノートを作成する", + "cli_stats_help": "統計を表示する", + "cli_gui_help": "ローカル Web インターフェースを開く", + "cli_content_help": "ノート本文", + "cli_type_help": "記録の種類(ノートまたはログ)", + "cli_category_help": "記録のカテゴリ", + "cli_title_help": "任意のタイトル", + "cli_mood_help": "気分の評価(1 から 5)", + "cli_limit_help": "読み込むノートの最大数", + "cli_term_help": "検索するテキスト", + "cli_topic_help": "ブレインストーミングのテーマ", + "cli_port_help": "ループバックサーバーのポート", + "cli_no_browser_help": "ブラウザーを開かずにサーバーを起動する", + "cli_gui_started": "llm-note ローカル Web インターフェース: {url}", + "cli_gui_stop": "終了するには Ctrl+C を押してください。" } diff --git a/llm_note/locales/ru.json b/llm_note/locales/ru.json index 8cafe7a..27a482e 100644 --- a/llm_note/locales/ru.json +++ b/llm_note/locales/ru.json @@ -2,5 +2,72 @@ "saved": "заметка #{id} сохранена ({category})", "no_results": "заметки не найдены", "brainstorm_saved": "заметка для мозгового штурма #{id} создана", - "stats_total": "заметок: {total}; повышено: {promoted}" + "stats_total": "заметок: {total}; повышено: {promoted}", + "gui_document_title": "llm-note Denkarium", + "gui_heading": "Denkarium", + "gui_subtitle": "Заметки · дневник · идеи", + "gui_compose_placeholder": "О чём вы сейчас думаете?", + "gui_note": "Заметка", + "gui_notes": "Заметки", + "gui_logbook": "Дневник", + "gui_category": "Категория", + "gui_optional_title": "Заголовок (необязательно)", + "gui_mood": "Настроение", + "gui_save": "Сохранить", + "gui_search": "Искать заметки …", + "gui_all": "Все", + "gui_entries": "записей", + "gui_empty_title": "Пустые страницы", + "gui_empty_body": "Напишите первую заметку.", + "gui_loading": "Загрузка …", + "gui_load_error": "Не удалось загрузить заметки.", + "gui_save_error": "Не удалось сохранить заметку.", + "gui_language": "Язык", + "gui_settings": "Настройки отображения", + "gui_filters": "Фильтры заметок", + "gui_content_label": "Текст заметки", + "gui_entry_type_label": "Тип записи", + "gui_category_label": "Категория", + "gui_title_label": "Заголовок", + "gui_mood_label": "Настроение", + "gui_font_serif": "С засечками", + "gui_font_sans": "Без засечек", + "gui_font_mono": "Моноширинный", + "cli_description": "Локальные заметки для LLM-агентов", + "cli_help_action": "показать эту справку и выйти", + "cli_usage_label": "использование", + "cli_positional_label": "позиционные аргументы", + "cli_options_label": "параметры", + "cli_error_label": "ошибка", + "cli_argument_error": "аргумент {argument}: {message}", + "cli_required_arguments": "не указаны обязательные аргументы: {arguments}", + "cli_unrecognized_arguments": "неизвестные аргументы: {arguments}", + "cli_expected_one_argument": "требуется один аргумент", + "cli_invalid_integer": "недопустимое целое число: {value}", + "cli_invalid_choice": "недопустимый вариант: {value} (доступные варианты: {choices})", + "cli_limit_integer": "limit должен быть целым числом", + "cli_limit_range": "limit должен быть от 0 до {max}", + "cli_port_integer": "port должен быть целым числом", + "cli_port_range": "port должен быть от 0 до 65535", + "cli_mood_integer": "mood должен быть целым числом", + "cli_db_help": "Путь к базе данных SQLite", + "cli_locale_help": "Язык сообщений; для GUI задаёт начальный язык", + "cli_write_help": "Создать заметку", + "cli_read_help": "Прочитать последние заметки", + "cli_search_help": "Найти заметки", + "cli_brainstorm_help": "Создать заметку для мозгового штурма", + "cli_stats_help": "Показать статистику", + "cli_gui_help": "Открыть локальный веб-интерфейс", + "cli_content_help": "Текст заметки", + "cli_type_help": "Тип записи (заметка или дневник)", + "cli_category_help": "Категория записи", + "cli_title_help": "Необязательный заголовок", + "cli_mood_help": "Оценка настроения от 1 до 5", + "cli_limit_help": "Максимальное число заметок для чтения", + "cli_term_help": "Текст для поиска", + "cli_topic_help": "Тема мозгового штурма", + "cli_port_help": "Порт loopback-сервера", + "cli_no_browser_help": "Запустить сервер без открытия браузера", + "cli_gui_started": "Локальный веб-интерфейс llm-note: {url}", + "cli_gui_stop": "Нажмите Ctrl+C, чтобы остановить сервер." } diff --git a/llm_note/locales/zh-Hans.json b/llm_note/locales/zh-Hans.json index f196f07..2fcd1fc 100644 --- a/llm_note/locales/zh-Hans.json +++ b/llm_note/locales/zh-Hans.json @@ -2,5 +2,72 @@ "saved": "已保存笔记 #{id}({category})", "no_results": "未找到笔记", "brainstorm_saved": "已创建头脑风暴笔记 #{id}", - "stats_total": "笔记:{total};已提升:{promoted}" + "stats_total": "笔记:{total};已提升:{promoted}", + "gui_document_title": "llm-note 思想集", + "gui_heading": "思想集", + "gui_subtitle": "笔记 · 日志 · 灵感", + "gui_compose_placeholder": "你在想些什么?", + "gui_note": "笔记", + "gui_notes": "笔记", + "gui_logbook": "日志", + "gui_category": "类别", + "gui_optional_title": "标题(可选)", + "gui_mood": "心情", + "gui_save": "保存", + "gui_search": "搜索笔记 …", + "gui_all": "全部", + "gui_entries": "条记录", + "gui_empty_title": "空白页面", + "gui_empty_body": "写下你的第一条笔记。", + "gui_loading": "正在加载 …", + "gui_load_error": "无法加载笔记。", + "gui_save_error": "无法保存笔记。", + "gui_language": "语言", + "gui_settings": "显示设置", + "gui_filters": "笔记筛选", + "gui_content_label": "笔记内容", + "gui_entry_type_label": "记录类型", + "gui_category_label": "类别", + "gui_title_label": "标题", + "gui_mood_label": "心情", + "gui_font_serif": "衬线", + "gui_font_sans": "无衬线", + "gui_font_mono": "等宽", + "cli_description": "面向 LLM 智能体的本地笔记", + "cli_help_action": "显示此帮助并退出", + "cli_usage_label": "用法", + "cli_positional_label": "位置参数", + "cli_options_label": "选项", + "cli_error_label": "错误", + "cli_argument_error": "参数 {argument}:{message}", + "cli_required_arguments": "以下参数为必填项:{arguments}", + "cli_unrecognized_arguments": "无法识别的参数:{arguments}", + "cli_expected_one_argument": "需要一个参数", + "cli_invalid_integer": "整数值无效:{value}", + "cli_invalid_choice": "选项无效:{value}(可选值:{choices})", + "cli_limit_integer": "limit 必须是整数", + "cli_limit_range": "limit 必须介于 0 和 {max} 之间", + "cli_port_integer": "port 必须是整数", + "cli_port_range": "port 必须介于 0 和 65535 之间", + "cli_mood_integer": "mood 必须是整数", + "cli_db_help": "SQLite 数据库路径", + "cli_locale_help": "消息语言;用于 GUI 时会设置初始显示语言", + "cli_write_help": "写入一条笔记", + "cli_read_help": "读取最近的笔记", + "cli_search_help": "搜索笔记", + "cli_brainstorm_help": "创建一条头脑风暴笔记", + "cli_stats_help": "显示统计信息", + "cli_gui_help": "打开本地网页界面", + "cli_content_help": "笔记内容", + "cli_type_help": "记录类型(笔记或日志)", + "cli_category_help": "记录类别", + "cli_title_help": "可选标题", + "cli_mood_help": "心情评分,范围为 1 到 5", + "cli_limit_help": "读取笔记的最大数量", + "cli_term_help": "要搜索的文本", + "cli_topic_help": "头脑风暴主题", + "cli_port_help": "本地回环服务器端口", + "cli_no_browser_help": "启动服务器但不打开浏览器", + "cli_gui_started": "llm-note 本地网页界面:{url}", + "cli_gui_stop": "按 Ctrl+C 停止服务器。" } diff --git a/llm_note/templates/denkarium.html b/llm_note/templates/denkarium.html index c43d2e3..8dcb9cb 100644 --- a/llm_note/templates/denkarium.html +++ b/llm_note/templates/denkarium.html @@ -75,6 +75,12 @@ font-family: "Segoe UI", Arial, sans-serif; font-size: 0.78rem; } + .settings-controls { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.5rem; + } .font-choice, button, input, @@ -191,6 +197,17 @@ .mood { margin-left: auto; color: var(--accent); letter-spacing: 0.08em; } .empty { padding: 3.5rem 1rem; text-align: center; color: var(--ink-faint); } .empty strong { display: block; margin-bottom: 0.4rem; font-size: 1.4rem; font-style: italic; } + .visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; + } @media (max-width: 620px) { main { padding-top: 1.6rem; } @@ -209,25 +226,40 @@

Denkarium

-
-
- - - +
+ +
+ + + + +
- + +
- - - - + + + + @@ -251,19 +284,56 @@

Denkarium