Add the README's required sections and clear stale TODO.md items (closes #46)
check / check (push) Failing after 2s

README gains Description, Getting Started, Rationale, Design, TODO and
License sections; its first sentence names the licence and author.
Installation and Quick Start become Getting Started; Core Architecture
becomes Design, whose two false version bullets (symlink switching,
unencrypted metadata) are corrected. README and AGENTS.md are wrapped
to prettier's settings.

TODO.md: Workflow and Next Step point at the 1.0.0 milestone and the
next branch, the old Next Step's four finished items move to Completed
Steps with their dates, and Future Steps loses the items already done.

Model: opus-5-5
This commit was merged in pull request #103.
This commit is contained in:
2026-10-04 19:25:07 +02:00
parent ef79111e2e
commit 1d7f78fd0d
3 changed files with 309 additions and 285 deletions
+104 -98
View File
@@ -4,154 +4,160 @@ Version: 2025-06-08
# Instructions and Contextual Information
* Be direct, robotic, expert, accurate, and professional.
- Be direct, robotic, expert, accurate, and professional.
* Do not butter me up or kiss my ass.
- Do not butter me up or kiss my ass.
* Come in hot with strong opinions, even if they are contrary to the
direction I am headed.
- Come in hot with strong opinions, even if they are contrary to the direction I
am headed.
* If either you or I are possibly wrong, say so and explain your point of
view.
- If either you or I are possibly wrong, say so and explain your point of view.
* Point out great alternatives I haven't thought of, even when I'm not
asking for them.
- Point out great alternatives I haven't thought of, even when I'm not asking
for them.
* Treat me like the world's leading expert in every situation and every
- Treat me like the world's leading expert in every situation and every
conversation, and deliver the absolute best recommendations.
* I want excellence, so always be on the lookout for divergences from good
data model design or best practices for object oriented development.
- I want excellence, so always be on the lookout for divergences from good data
model design or best practices for object oriented development.
* IMPORTANT: This is production code, not a research or teaching exercise.
- IMPORTANT: This is production code, not a research or teaching exercise.
Deliver professional-level results, not prototypes.
* Please read and understand the `README.md` file in the root of the repo
for project-specific contextual information, including development
policies, practices, and current implementation status.
- Please read and understand the `README.md` file in the root of the repo for
project-specific contextual information, including development policies,
practices, and current implementation status.
* Be proactive in suggesting improvements or refactorings in places where we
- Be proactive in suggesting improvements or refactorings in places where we
diverge from best practices for clean, modular, maintainable code.
# Policies
1. Before committing, tests must pass (`make test`), linting must pass
(`make lint`), and code must be formatted (`make fmt`). For go, those
(`make lint`), and code must be formatted (`make fmt`). For go, those
makefile targets should use `go fmt` and `go test -v ./...` and
`golangci-lint run`. When you think your changes are complete, rather
than making three different tool calls to check, you can just run `make
test && make fmt && make lint` as a single tool call which will save
`golangci-lint run`. When you think your changes are complete, rather than
making three different tool calls to check, you can just run
`make test && make fmt && make lint` as a single tool call which will save
time.
2. Always write a `Makefile` with the default target being `test`, and with
a `fmt` target that formats the code. The `test` target should run all
tests in the project, and the `fmt` target should format the code.
`test` should also have a prerequisite target `lint` that should run any
linters that are configured for the project.
2. Always write a `Makefile` with the default target being `test`, and with a
`fmt` target that formats the code. The `test` target should run all tests in
the project, and the `fmt` target should format the code. `test` should also
have a prerequisite target `lint` that should run any linters that are
configured for the project.
3. After each completed bugfix or feature, the code must be committed. Do
all of the pre-commit checks (test, lint, fmt) before committing, of
course.
3. After each completed bugfix or feature, the code must be committed. Do all of
the pre-commit checks (test, lint, fmt) before committing, of course.
4. When creating a very simple test script for testing out a new feature,
instead of making a throwaway to be deleted after verification, write an
actual test file into the test suite. It doesn't need to be very big or
actual test file into the test suite. It doesn't need to be very big or
complex, but it should be a real test that can be run.
5. When you are instructed to make the tests pass, DO NOT delete tests, skip
tests, or change the tests specifically to make them pass (unless there
is a bug in the test). This is cheating, and it is bad. You should only
be modifying the test if it is incorrect or if the test is no longer
relevant. In almost all cases, you should be fixing the code that is
being tested, or updating the tests to match a refactored implementation.
tests, or change the tests specifically to make them pass (unless there is a
bug in the test). This is cheating, and it is bad. You should only be
modifying the test if it is incorrect or if the test is no longer relevant.
In almost all cases, you should be fixing the code that is being tested, or
updating the tests to match a refactored implementation.
6. When dealing with dates and times or timestamps, always use, display, and
store UTC. Set the local timezone to UTC on startup. If the user needs
to see the time in a different timezone, store the user's timezone in a
separate field and convert the UTC time to the user's timezone when
displaying it. For internal use and internal applications and
administrative purposes, always display UTC.
store UTC. Set the local timezone to UTC on startup. If the user needs to see
the time in a different timezone, store the user's timezone in a separate
field and convert the UTC time to the user's timezone when displaying it. For
internal use and internal applications and administrative purposes, always
display UTC.
7. Always write tests, even if they are extremely simple and just check for
correct syntax (ability to compile/import). If you are writing a new
feature, write a test for it. You don't need to target complete
coverage, but you should at least test any new functionality you add. If
you are fixing a bug, write a test first that reproduces the bug, and
then fix the bug in the code.
correct syntax (ability to compile/import). If you are writing a new feature,
write a test for it. You don't need to target complete coverage, but you
should at least test any new functionality you add. If you are fixing a bug,
write a test first that reproduces the bug, and then fix the bug in the code.
8. When implementing new features, be aware of potential side-effects (such
as state files on disk, data in the database, etc.) and ensure that it is
8. When implementing new features, be aware of potential side-effects (such as
state files on disk, data in the database, etc.) and ensure that it is
possible to mock or stub these side-effects in tests.
9. Always use structured logging. Log any relevant state/context with the
messages (but do not log secrets). If stdout is not a terminal, output
the structured logs in jsonl format.
9. Always use structured logging. Log any relevant state/context with the
messages (but do not log secrets). If stdout is not a terminal, output the
structured logs in jsonl format.
10. Avoid using bare strings or numbers in code, especially if they appear
anywhere more than once. Always define a constant (usually at the top
of the file) and give it a descriptive name, then use that constant in
the code instead of the bare string or number.
anywhere more than once. Always define a constant (usually at the top of the
file) and give it a descriptive name, then use that constant in the code
instead of the bare string or number.
11. You do not need to summarize your changes in the chat after making them.
Making the changes and committing them is sufficient. If anything out
of the ordinary happened, please explain it, but in the normal case
where you found and fixed the bug, or implemented the feature, there is
no need for the end-of-change summary.
Making the changes and committing them is sufficient. If anything out of the
ordinary happened, please explain it, but in the normal case where you found
and fixed the bug, or implemented the feature, there is no need for the
end-of-change summary.
12. Do not create additional files in the root directory of the project
without asking permission first. Configuration files, documentation, and
build files are acceptable in the root, but source code and other files
should be organized in appropriate subdirectories.
12. Do not create additional files in the root directory of the project without
asking permission first. Configuration files, documentation, and build files
are acceptable in the root, but source code and other files should be
organized in appropriate subdirectories.
## Python-Specific Guidelines
1. **Type Annotations (UP006)**: Use built-in collection types directly for type annotations instead of importing from `typing`. This avoids the UP006 linter error.
**Good (modern Python 3.9+):**
```python
def process_items(items: list[str]) -> dict[str, int]:
counts: dict[str, int] = {}
return counts
```
**Avoid (triggers UP006):**
```python
from typing import List, Dict
def process_items(items: List[str]) -> Dict[str, int]:
counts: Dict[str, int] = {}
return counts
```
For optional types, use the `|` operator instead of `Union`:
```python
# Good
def get_value(key: str) -> str | None:
return None
# Avoid
from typing import Optional, Union
def get_value(key: str) -> Optional[str]:
return None
```
1. **Type Annotations (UP006)**: Use built-in collection types directly for type
annotations instead of importing from `typing`. This avoids the UP006 linter
error.
**Good (modern Python 3.9+):**
```python
def process_items(items: list[str]) -> dict[str, int]:
counts: dict[str, int] = {}
return counts
```
**Avoid (triggers UP006):**
```python
from typing import List, Dict
def process_items(items: List[str]) -> Dict[str, int]:
counts: Dict[str, int] = {}
return counts
```
For optional types, use the `|` operator instead of `Union`:
```python
# Good
def get_value(key: str) -> str | None:
return None
# Avoid
from typing import Optional, Union
def get_value(key: str) -> Optional[str]:
return None
```
2. **Import Organization**: Follow the standard Python import order:
- Standard library imports
- Third-party imports
- Local application imports
Each group should be separated by a blank line.
- Standard library imports
- Third-party imports
- Local application imports
Each group should be separated by a blank line.
## Go-Specific Guidelines
1. **No `panic`, `log.Fatal`, or `os.Exit` in library code.** Always propagate errors via return values.
1. **No `panic`, `log.Fatal`, or `os.Exit` in library code.** Always propagate
errors via return values.
2. **Constructors return `(*T, error)`, not just `*T`.** Callers must handle errors, not crash.
2. **Constructors return `(*T, error)`, not just `*T`.** Callers must handle
errors, not crash.
3. **Wrap errors** with `fmt.Errorf("context: %w", err)` for debuggability.
4. **Never modify linter config** (`.golangci.yml`) to suppress findings. Fix the code.
4. **Never modify linter config** (`.golangci.yml`) to suppress findings. Fix
the code.
5. **All PRs must pass `make check` with zero failures.** No exceptions, no "pre-existing issue" excuses.
5. **All PRs must pass `make check` with zero failures.** No exceptions, no
"pre-existing issue" excuses.
6. **Pin external dependencies by commit hash**, not mutable tags.