tg-notes 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tg_notes-0.1.0/.claude-plugin/marketplace.json +18 -0
- tg_notes-0.1.0/.claude-plugin/plugin.json +13 -0
- tg_notes-0.1.0/.github/workflows/ci.yml +28 -0
- tg_notes-0.1.0/.github/workflows/release.yml +35 -0
- tg_notes-0.1.0/.gitignore +21 -0
- tg_notes-0.1.0/AGENTS.md +20 -0
- tg_notes-0.1.0/CHANGELOG.md +133 -0
- tg_notes-0.1.0/CLAUDE.md +64 -0
- tg_notes-0.1.0/LICENSE +674 -0
- tg_notes-0.1.0/PKG-INFO +140 -0
- tg_notes-0.1.0/README.md +116 -0
- tg_notes-0.1.0/TODO.md +75 -0
- tg_notes-0.1.0/docs/architecture.md +118 -0
- tg_notes-0.1.0/docs/features.md +36 -0
- tg_notes-0.1.0/pyproject.toml +44 -0
- tg_notes-0.1.0/skills/tg-notes/SKILL.md +73 -0
- tg_notes-0.1.0/skills/tg-notes-send/SKILL.md +83 -0
- tg_notes-0.1.0/tests/__init__.py +0 -0
- tg_notes-0.1.0/tests/test_cli.py +533 -0
- tg_notes-0.1.0/tests/test_config.py +67 -0
- tg_notes-0.1.0/tests/test_contacts.py +215 -0
- tg_notes-0.1.0/tests/test_notebooks.py +68 -0
- tg_notes-0.1.0/tests/test_notes.py +248 -0
- tg_notes-0.1.0/tests/test_send.py +161 -0
- tg_notes-0.1.0/tests/test_setup.py +265 -0
- tg_notes-0.1.0/tests/test_telegram.py +81 -0
- tg_notes-0.1.0/tg_notes/__init__.py +4 -0
- tg_notes-0.1.0/tg_notes/cli.py +391 -0
- tg_notes-0.1.0/tg_notes/config.py +81 -0
- tg_notes-0.1.0/tg_notes/contacts.py +101 -0
- tg_notes-0.1.0/tg_notes/telegram.py +535 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tg-notes-marketplace",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "korkin25"
|
|
5
|
+
},
|
|
6
|
+
"description": "Marketplace for the tg-notes plugin — Telegram-backed notes → compiled reports.",
|
|
7
|
+
"plugins": [
|
|
8
|
+
{
|
|
9
|
+
"name": "tg-notes",
|
|
10
|
+
"source": "./",
|
|
11
|
+
"description": "Notes → compile → publish via a private Telegram group, under your own account.",
|
|
12
|
+
"version": "0.1.0",
|
|
13
|
+
"homepage": "https://github.com/korkin25/tg_notes",
|
|
14
|
+
"license": "GPL-3.0-or-later",
|
|
15
|
+
"keywords": ["telegram", "notes", "userbot", "reports", "cli"]
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tg-notes",
|
|
3
|
+
"description": "Notes → compile → publish via a private Telegram group, posting under your own account. Bundles the tg-notes capture and compile-&-send skills, which drive the tg-notes CLI (install separately: pipx install tg-notes).",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "korkin25",
|
|
7
|
+
"url": "https://github.com/korkin25"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/korkin25/tg_notes",
|
|
10
|
+
"repository": "https://github.com/korkin25/tg_notes",
|
|
11
|
+
"license": "GPL-3.0-or-later",
|
|
12
|
+
"keywords": ["telegram", "notes", "userbot", "reports", "cli"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.11", "3.12"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Install (with dev extras)
|
|
20
|
+
run: pip install -e .[dev]
|
|
21
|
+
- name: Lint (ruff)
|
|
22
|
+
run: ruff check .
|
|
23
|
+
- name: Test (pytest)
|
|
24
|
+
run: pytest -q
|
|
25
|
+
- name: Security scan (bandit)
|
|
26
|
+
run: bandit -r tg_notes
|
|
27
|
+
- name: Dependency audit (pip-audit)
|
|
28
|
+
run: pip-audit
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Triggered by pushing a SemVer tag (vX.Y.Z). Builds the distribution and
|
|
4
|
+
# publishes it to PyPI via Trusted Publishing (OIDC) — no API token in secrets.
|
|
5
|
+
#
|
|
6
|
+
# ONE-TIME PyPI SETUP (before the first tag): on PyPI, add a Trusted Publisher for
|
|
7
|
+
# the project `tg-notes` bound to repo `korkin25/tg_notes`, workflow
|
|
8
|
+
# `release.yml`, environment `pypi`. Until that exists, the publish step fails by
|
|
9
|
+
# design. Publishing is deliberate — this runs only on a `v*` tag, which is cut
|
|
10
|
+
# only after the full suite is green on `main`.
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
tags:
|
|
15
|
+
- "v*"
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
release:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
environment: pypi
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write # OIDC token for PyPI Trusted Publishing
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
- name: Install build backend
|
|
29
|
+
run: pip install build
|
|
30
|
+
- name: Build distribution
|
|
31
|
+
run: python -m build
|
|
32
|
+
- name: Check distribution metadata
|
|
33
|
+
run: pipx run twine check dist/*
|
|
34
|
+
- name: Publish to PyPI
|
|
35
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtualenvs
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
|
|
13
|
+
# Secrets / auth — never commit
|
|
14
|
+
*.session
|
|
15
|
+
*.session-journal
|
|
16
|
+
.env
|
|
17
|
+
config.toml
|
|
18
|
+
config.json
|
|
19
|
+
|
|
20
|
+
# Claude Code personal (local) settings — never commit
|
|
21
|
+
.claude/settings.local.json
|
tg_notes-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file is the standard entry point that AI coding agents look for.
|
|
4
|
+
|
|
5
|
+
**The canonical rules for this repository live in [CLAUDE.md](CLAUDE.md).** Read it
|
|
6
|
+
first: it defines the language rules, the documentation-sync policy, the security
|
|
7
|
+
conventions, and the autonomous development workflow (TDD, feature branches,
|
|
8
|
+
Conventional Commits, CI, releases). Everything in `CLAUDE.md` applies to every
|
|
9
|
+
agent working here, not only to Claude Code.
|
|
10
|
+
|
|
11
|
+
## Cross-agent portability
|
|
12
|
+
|
|
13
|
+
This project follows the **Agent Skills** standard (<https://agentskills.io>) and its
|
|
14
|
+
`SKILL.md` format. Skills are authored once as plain `SKILL.md` files (standard core
|
|
15
|
+
frontmatter: `name`, `description`) so the same skill is read unchanged by any
|
|
16
|
+
Agent-Skills-compatible runtime — Claude Code, OpenCode, Hermes, and others — with no
|
|
17
|
+
per-agent rewrite. Only *distribution* differs per agent (plugin marketplace, `~/.claude/skills`
|
|
18
|
+
discovery, or a runtime's own skill store); the skill content stays portable.
|
|
19
|
+
|
|
20
|
+
For anything an agent needs to know or do in this repo, defer to `CLAUDE.md`.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
6
|
+
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-07-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Project documentation and rules: `README.md`, `CLAUDE.md` (language and doc-sync
|
|
15
|
+
rules), `docs/architecture.md`, `docs/features.md`.
|
|
16
|
+
- Implementation plan in `TODO.md` (planning phase; no code yet).
|
|
17
|
+
- `GPL-3.0` license (`LICENSE`).
|
|
18
|
+
- Project scaffolding (TGN-1): `pyproject.toml` (CLI `tg-notes`, Telethon dependency,
|
|
19
|
+
editable-installable), `tg_notes` package, argparse command tree (`setup`, `note add`,
|
|
20
|
+
`notes list`, `contacts list/set/remove`, `send`, `notebooks list` — stubs so far),
|
|
21
|
+
local TOML config module (XDG path, `chmod 600`), and `.gitignore` for secrets and
|
|
22
|
+
`*.session`.
|
|
23
|
+
- Autonomous development-workflow rules in `CLAUDE.md` (TDD-first, feature branches,
|
|
24
|
+
Conventional Commits, tag-based SemVer releases, CI expectations, security bar),
|
|
25
|
+
replacing the previous minimal `Git` section.
|
|
26
|
+
- GitHub Actions workflows: CI (`.github/workflows/ci.yml`) running ruff, pytest
|
|
27
|
+
(Python 3.11 and 3.12), bandit, and pip-audit on every push and pull request; and
|
|
28
|
+
release (`.github/workflows/release.yml`) building and publishing to PyPI on `v*` tags.
|
|
29
|
+
- `dev` optional-dependency group in `pyproject.toml` (`pytest`, `pytest-mock`, `ruff`,
|
|
30
|
+
`bandit`, `pip-audit`, `build`).
|
|
31
|
+
- `AGENTS.md` pointing agents to `CLAUDE.md` as the canonical rules and documenting the
|
|
32
|
+
Agent Skills (`SKILL.md`) portability standard.
|
|
33
|
+
- Telegram client layer (TGN-2): `tg_notes/telegram.py` — a synchronous Telethon wrapper
|
|
34
|
+
(`import telethon.sync`) with `build_client` / `connect_authorized` / `whoami` / `login`
|
|
35
|
+
and typed `NotConfiguredError` / `NotAuthorizedError`. Sessions are locked to `chmod 600`
|
|
36
|
+
after login.
|
|
37
|
+
- CLI commands `login` (one-time interactive phone/code/2FA login, stores the session) and
|
|
38
|
+
`whoami` (prints the logged-in account identity as JSON); both report missing credentials
|
|
39
|
+
or an unauthorized session with a clear message and a nonzero exit.
|
|
40
|
+
- Test suite under `tests/` (pytest + pytest-mock): config round-trip / file mode / session
|
|
41
|
+
path, the Telegram layer with Telethon fully mocked (offline), and the CLI argument
|
|
42
|
+
surface. Pytest and ruff config added to `pyproject.toml`.
|
|
43
|
+
- Storage provisioning (TGN-3): `tg-notes setup` creates (or idempotently attaches to) the
|
|
44
|
+
private forum supergroup that stores notes. It ensures the `contacts` topic and a default
|
|
45
|
+
`daily` notebook topic (override with `--notebook`), pins a recovery marker in the group
|
|
46
|
+
so a lost store can be re-discovered, and persists the resolved group id to local config.
|
|
47
|
+
New `telegram.setup` plus helpers (`_resolve_or_create` / `_create_storage_group` /
|
|
48
|
+
`_ensure_topics` / `_pin_marker`) built on Telethon's forum raw API
|
|
49
|
+
(`CreateChannelRequest(megagroup=True, forum=True)`, `CreateForumTopicRequest`,
|
|
50
|
+
`GetForumTopicsRequest`); tests in `tests/test_setup.py` with Telethon fully mocked.
|
|
51
|
+
`setup` drives first-run onboarding itself: when `api_id`/`api_hash` are missing it
|
|
52
|
+
prompts for them and saves them to local config (mode 600); when the device is not
|
|
53
|
+
logged in it runs the interactive `login` (phone → code → 2FA) and retries the
|
|
54
|
+
provisioning. If the prompt is left blank (or the values are unusable) it falls back to
|
|
55
|
+
printing step-by-step manual guidance (my.telegram.org → config path → `chmod 600` →
|
|
56
|
+
`login` → re-run) and exits nonzero.
|
|
57
|
+
- Note capture (TGN-4): `tg-notes note add --notebook <nb> --text-file <f>` appends a note
|
|
58
|
+
to the notebook's forum topic, creating the topic on demand. Reads the note text from a
|
|
59
|
+
file or stdin (`--text-file -`), appends optional `--hashtag TAG` tokens (repeatable) on
|
|
60
|
+
a trailing line, refuses to post an empty note, and prints the posted note as JSON
|
|
61
|
+
(`notebook` / `topic_id` / `message_id` / `date`). New `telegram.note_add` (+ helpers
|
|
62
|
+
`_compose_note` / `_normalize_hashtag`) and a `NotSetUpError` that tells the user to run
|
|
63
|
+
`setup` first; tests in `tests/test_notes.py` with Telethon fully mocked.
|
|
64
|
+
- Note listing (TGN-5): `tg-notes notes list --notebook <nb> [--since <t>]` returns a
|
|
65
|
+
notebook's raw notes as a JSON array (oldest first), each `{message_id, date, text}`,
|
|
66
|
+
skipping the topic-opening service message. `--since` accepts `today`, `HH:MM`,
|
|
67
|
+
`YYYY-MM-DD`, or a full ISO datetime (interpreted as local time when it carries no
|
|
68
|
+
offset) and bounds the messages by date; an unknown notebook yields `[]`. New
|
|
69
|
+
`telegram.notes_list` and a CLI `_parse_since` parser; tests in `tests/test_notes.py`
|
|
70
|
+
and `tests/test_cli.py` (Telethon mocked).
|
|
71
|
+
- Contacts address book (TGN-6): `tg-notes contacts list|set|remove` over the
|
|
72
|
+
message-per-contact schema in the `contacts` topic. New pure `tg_notes.contacts` module
|
|
73
|
+
((de)serializes the `#contact <key>` block; single-line fields, colons preserved) plus
|
|
74
|
+
`telegram.contacts_list` / `contacts_set` / `contacts_remove`. `set` creates or updates
|
|
75
|
+
in place (only the given fields override an existing record; a new contact requires
|
|
76
|
+
`--chat-id`; edits reuse the same message), `remove` deletes the contact's message
|
|
77
|
+
(missing key is a no-op), `list` returns all contacts as JSON sorted by key. Tests in
|
|
78
|
+
`tests/test_contacts.py` (pure + Telethon-mocked layer). Refactor: shared
|
|
79
|
+
`_resolve_store` helper (in `tg_notes.telegram`) and `_handle_store_errors` /
|
|
80
|
+
`_STORE_ERRORS` (in the CLI) deduplicate the not-set-up / not-configured / not-authorized
|
|
81
|
+
handling across `note add`, `notes list`, and `contacts`.
|
|
82
|
+
- Publish (TGN-7): `tg-notes send --contact <key> --text-file <f>` posts compiled text to a
|
|
83
|
+
contact's chat **as the user** — into a forum topic (`reply_to`) when the contact has a
|
|
84
|
+
`topic_id`, prepending the contact's `mention` on its own line when set. Text comes from
|
|
85
|
+
a file or stdin (`-`); `--dry-run` composes and prints the outgoing message (target,
|
|
86
|
+
topic, text) without sending. New `telegram.send` (+ `_compose_outgoing` /
|
|
87
|
+
`_target_from_chat_id`, resolving `chat_id` as `-100…` int or `@user` / `me`) and a
|
|
88
|
+
`ContactNotFoundError` (CLI exit 5); empty text is refused. Tests in `tests/test_send.py`
|
|
89
|
+
(Telethon mocked). This is the first command that posts outside the storage group.
|
|
90
|
+
- Notebook listing (TGN-8): `tg-notes notebooks list` returns the storage group's notebook
|
|
91
|
+
topics as JSON (`{name, topic_id}`, sorted), excluding the reserved `General` and
|
|
92
|
+
`contacts` topics. New `telegram.notebooks_list` and `RESERVED_TOPICS`; tests in
|
|
93
|
+
`tests/test_notebooks.py`. Completes **Phase 1 (CLI core)** — all deterministic Telegram
|
|
94
|
+
commands are implemented and verified end-to-end. Removed the leftover `_todo` stub
|
|
95
|
+
handler now that no command is a stub.
|
|
96
|
+
- Capture skill (TGN-9): `skills/tg-notes/SKILL.md` — a portable Agent Skill (standard
|
|
97
|
+
`name`/`description` frontmatter) that captures a work note into the Telegram-backed
|
|
98
|
+
store by shelling out to `tg-notes note add`. Two modes: verbatim (user dictates) and
|
|
99
|
+
session summary (composed from real facts — git commits since 00:00, changed files,
|
|
100
|
+
tickets — never invented), 2–6 concise bullets in the user's language, default `daily`
|
|
101
|
+
notebook, optional hashtags. Capture only — it never sends. Verified end-to-end against
|
|
102
|
+
the real account (both modes filed and read back). Succeeds the retired local `report`
|
|
103
|
+
skill, now Telegram-native.
|
|
104
|
+
- Compile & send skill (TGN-10): `skills/tg-notes-send/SKILL.md` — reads notes
|
|
105
|
+
(`tg-notes notes list`), rewrites them per the target contact's `style`, previews with
|
|
106
|
+
`tg-notes send --dry-run`, **always shows a draft and requires an explicit confirmation**
|
|
107
|
+
(the message goes out under the user's own account), then `tg-notes send`. Contacts are
|
|
108
|
+
the single source of chat/topic/mention/style. Verified end-to-end against the real
|
|
109
|
+
account (dry-run → confirmed send to Saved Messages → read back; unknown-contact exit 5).
|
|
110
|
+
Succeeds the retired local `report-send` skill, now driven by the `tg-notes` CLI.
|
|
111
|
+
- Daily-report preset (TGN-11): a first-class section of `skills/tg-notes-send/SKILL.md`
|
|
112
|
+
(`/tg-report`, "отправь дневной отчёт") — the compile & send flow with fixed defaults
|
|
113
|
+
(notebook `daily`, `--since today`), one confirmed send per recipient. Completes
|
|
114
|
+
**Phase 2 (the Claude Code Skill)**: capture (`tg-notes`) + compile & send / daily report
|
|
115
|
+
(`tg-notes-send`), the Telegram-native successor to the old `report`/`report-send` pair.
|
|
116
|
+
- Claude Code plugin packaging (TGN-13): `.claude-plugin/plugin.json` — plugin manifest
|
|
117
|
+
(`name: tg-notes`, version, author, GPL-3.0-or-later) that bundles the two skills
|
|
118
|
+
(auto-discovered from `skills/`). Passes `claude plugin validate . --strict`.
|
|
119
|
+
- Git plugin marketplace (TGN-14): `.claude-plugin/marketplace.json` — single-plugin
|
|
120
|
+
marketplace (`tg-notes-marketplace`) with `source: "./"` (plugin is the repo root).
|
|
121
|
+
Install: `/plugin marketplace add korkin25/tg_notes` then
|
|
122
|
+
`/plugin install tg-notes@tg-notes-marketplace`. The bundled skills drive the `tg-notes`
|
|
123
|
+
CLI, installed separately with `pipx install tg-notes`.
|
|
124
|
+
|
|
125
|
+
### Changed
|
|
126
|
+
|
|
127
|
+
- Single-source the package version: `pyproject.toml` reads it from
|
|
128
|
+
`tg_notes/__init__.py` (`[tool.hatch.version]`, `dynamic = ["version"]`) so it can no
|
|
129
|
+
longer drift between the two. Bumped to `0.1.0` for the first release.
|
|
130
|
+
- Release workflow (`.github/workflows/release.yml`) now publishes to PyPI via **Trusted
|
|
131
|
+
Publishing** (OIDC, `id-token: write`, `pypi` environment) instead of a stored API
|
|
132
|
+
token, and runs `twine check` on the built artifacts. Publishing still triggers only on
|
|
133
|
+
a `v*` tag; it needs a one-time PyPI Trusted Publisher bound to `korkin25/tg_notes`.
|
tg_notes-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guidance for Claude Code (and other AI agents) working in this repository.
|
|
4
|
+
|
|
5
|
+
## What this project is
|
|
6
|
+
|
|
7
|
+
`tg_notes` — a general-purpose **notes → compile → publish** tool that uses a private
|
|
8
|
+
Telegram forum group as its store and posts under the user's own account (userbot).
|
|
9
|
+
Daily work reports are one preset built on top of it.
|
|
10
|
+
|
|
11
|
+
Architecture in one line: a standalone Python CLI (`tg-notes`, Telethon/MTProto) does
|
|
12
|
+
all Telegram I/O; thin per-agent Skill wrappers (Claude Code first) add the
|
|
13
|
+
intelligence (composing notes, compiling them per recipient). See
|
|
14
|
+
[docs/architecture.md](docs/architecture.md).
|
|
15
|
+
|
|
16
|
+
Status: **planning** — no implementation yet. The plan lives in [TODO.md](TODO.md).
|
|
17
|
+
|
|
18
|
+
## Language rules (STRICT)
|
|
19
|
+
|
|
20
|
+
- **All repository content is English** — code, identifiers, comments, docstrings,
|
|
21
|
+
commit messages, and every document (README, `docs/`, CHANGELOG, TODO, this file).
|
|
22
|
+
No exceptions.
|
|
23
|
+
- **Conversation with the user is always Russian** — reply in Russian regardless of
|
|
24
|
+
the language they wrote in. This applies only to the live chat, never to anything
|
|
25
|
+
written into the repo.
|
|
26
|
+
|
|
27
|
+
## Documentation sync (apply without being asked)
|
|
28
|
+
|
|
29
|
+
Keep docs in lockstep with the code, **in the same change**:
|
|
30
|
+
|
|
31
|
+
| What changed | Update |
|
|
32
|
+
|---|---|
|
|
33
|
+
| New or changed feature / behavior | `docs/features.md` + `README.md` |
|
|
34
|
+
| CLI surface (commands, flags) | `README.md` (usage) + `docs/architecture.md` |
|
|
35
|
+
| Architecture, storage schema, data flow, security model | `docs/architecture.md` |
|
|
36
|
+
| Any user-visible change | `CHANGELOG.md` under `## [Unreleased]` |
|
|
37
|
+
| Task started / finished / blocked | `TODO.md` status |
|
|
38
|
+
|
|
39
|
+
- `CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/) + SemVer.
|
|
40
|
+
- `TODO.md` holds only open/in-progress work; when a task is done and verified, move
|
|
41
|
+
it out of `TODO.md` into `CHANGELOG.md`.
|
|
42
|
+
- Never mark a task done without confirmation that it actually works.
|
|
43
|
+
|
|
44
|
+
## Conventions
|
|
45
|
+
|
|
46
|
+
- **Secrets never leave the machine.** `api_id`/`api_hash`, the Telethon `*.session`
|
|
47
|
+
file, and local config are git-ignored. **Notes and contacts live only in Telegram.**
|
|
48
|
+
- The session file grants full account access: `chmod 600`, never committed.
|
|
49
|
+
- Userbot automation is a Telegram-ToS gray area; the tool only publishes the user's
|
|
50
|
+
own notes/reports and must stay non-spammy.
|
|
51
|
+
|
|
52
|
+
## Development workflow (autonomous — apply without being asked)
|
|
53
|
+
|
|
54
|
+
This project is developed by an AI agent under continuous, autonomous iteration.
|
|
55
|
+
|
|
56
|
+
- Test-driven: for every agreed feature write the tests FIRST (they must fail), then implement until green. No feature code without a test.
|
|
57
|
+
- Feature branches: work on feature/<task-id>-<slug> off main; merge to main only when the full suite is green.
|
|
58
|
+
- Commit periodically in small logical units, Conventional Commits (feat:, fix:, test:, docs:, chore:, ci:). Never add a Co-Authored-By trailer. Push to `origin` after every commit.
|
|
59
|
+
- Releases only after green tests: tag vX.Y.Z (SemVer) after the full suite passes on main. Publishing to PyPI or marketplaces is a separate, later, explicit step.
|
|
60
|
+
- CI on every push (GitHub Actions): ruff lint, pytest (3.11 and 3.12), security scan (bandit + pip-audit). A tag triggers the build/release job.
|
|
61
|
+
- Security first: no secrets in git; least privilege; treat the Telethon session / bot token as full-access credentials.
|
|
62
|
+
- High bar: type hints, docstrings, ruff-clean, meaningful tests. Work like a top-tier engineer + DevOps.
|
|
63
|
+
- Auto-logging: started/ongoing work goes to TODO.md (Current state + phase tables); completed and verified work moves to CHANGELOG.md, in the same change. Never mark a task done without a passing test.
|
|
64
|
+
- Cold-start: keep the top of TODO.md a "Current state / next action" block so a fresh session knows exactly what to do next.
|