Compress always-on contracts and restore pagination fields

The always-on set is paid by every session, so it gets the tightest
form: git-sync-check shrinks to its procedural core, testing-policy
moves the table-test example to README.md and folds the agent
instructions into the rules, go-code-style inlines the error-wrapping
example. Per-session read cost drops from 403 to 336 lines.

Also restore the pagination response fields in table-management: the
previous dedup replaced them with a reference to go-api, which the
table router line does not load.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 10:05:00 +03:00
parent a44133aff2
commit 0005f3e41a
5 changed files with 53 additions and 93 deletions

View File

@@ -2,40 +2,21 @@
## Rule
Before starting any work on a task, check whether the remote repository has commits that are not yet present locally.
This rule assumes the repository is hosted in Gitea.
Use neutral `git` commands for sync checks and branch management, and use Gitea terminology for server-side review flow (`pull request`, not `merge request`).
Before starting any work on a task (repositories are hosted in Gitea):
## Required Steps
1. `git fetch origin`
2. `git log HEAD..@{u} --oneline`
3. Non-empty output: **stop immediately, make no changes**, tell the user the remote has
new commits and ask how to proceed (pull, rebase, ignore).
4. Empty output: proceed normally.
1. Run `git fetch origin` to update remote-tracking refs from the Gitea remote without merging.
2. Check for upstream commits: `git log HEAD..@{u} --oneline`.
3. If the output is non-empty (there are new remote commits):
- **Stop immediately. Do not make any changes.**
- Inform the user that the remote has new commits and ask how to proceed (e.g., pull, rebase, or ignore).
4. If the output is empty, proceed with the task normally.
If offline and fetch is impossible: notify the user before proceeding.
Web UI inspection does not replace the local check.
## Gitea Workflow Notes
## Gitea Workflow
- Verify the remote when needed: `git remote -v`
- Create a task branch before changes: `git checkout -b <task-branch>`
- Push the branch to Gitea and set upstream: `git push -u origin <task-branch>`
- Open the review in Gitea as a pull request against the target branch.
- If the `tea` CLI is configured for the environment, it may be used for Gitea pull request actions such as:
- `tea pr list`
- `tea pr create`
- `tea pr checkout <number>`
## Forbidden Assumptions
- Do not assume GitHub-specific tooling such as `gh`.
- Do not use GitLab terminology such as `merge request` unless a project explicitly defines that workflow separately.
- Do not replace the required sync check with web UI inspection in Gitea; the local `git fetch origin` and `git log HEAD..@{u} --oneline` check remains mandatory.
## Rationale
Working on an outdated local state risks merge conflicts, duplicate work, and overwriting changes made by other contributors. Checking remote state first keeps the working tree aligned and prevents avoidable conflicts. Using Gitea-specific review terminology and examples also avoids workflow confusion in repositories that are not hosted on GitHub or GitLab.
## Exceptions
- Offline environments where `git fetch origin` is not possible: notify the user that the check could not be performed before proceeding.
- Create a task branch before changes (`git checkout -b <branch>`), push with
`git push -u origin <branch>`, review via a Gitea **pull request** (the `tea` CLI may be
used if configured).
- Do not assume GitHub tooling such as `gh`; do not use GitLab terminology such as
`merge request`.

View File

@@ -1,6 +1,6 @@
# Contract: Go Code Style and Project Conventions
Version: 1.2
Version: 1.3
## Source Text and Comments
@@ -17,18 +17,8 @@ Summary: use `slog`, log to stdout/stderr (binary console), never to browser con
## Error Handling
Always wrap errors with context. Use `fmt.Errorf("...: %w", err)`.
```go
// CORRECT
if err := db.Save(&record).Error; err != nil {
return fmt.Errorf("save component %s: %w", record.ID, err)
}
// WRONG: loses context
return err
```
- Always wrap errors with context: `fmt.Errorf("save component %s: %w", record.ID, err)`.
A bare `return err` loses context.
- Never silently discard errors with `_` in production paths.
- Return errors up the call stack; log at the handler/task boundary, not deep in service code.

View File

@@ -91,7 +91,8 @@ Canonical mapping:
## Pagination Rules
- Pagination is server-side. Never load all rows and paginate client-side.
- Query parameters and list response metadata follow the `go-api` contract.
- Query parameters carry page state (`?page=2&per_page=50`); the response includes
`total_count`, `page`, `per_page`, `total_pages` (shape per the `go-api` contract).
- `page` is 1-based; `per_page` defaults to a fixed project constant (e.g. 50) and may be
changed from a fixed set (25 / 50 / 100).
- Display: "Showing 51100 of 342" — always show the range and total.

View File

@@ -0,0 +1,26 @@
# Testing Policy Pattern Notes
This file keeps examples. The normative rules live in `contract.md`.
## Табличный тест
```go
func TestParseGPUSensor(t *testing.T) {
tests := []struct {
name string
xml string
want int
}{
{"normal", `<VALUE>290</VALUE>`, 29},
{"zero", `<VALUE>0</VALUE>`, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := parseGPUTemp(tt.xml)
if got != tt.want {
t.Fatalf("got %d, want %d", got, tt.want)
}
})
}
}
```

View File

@@ -1,13 +1,12 @@
# Contract: Testing Policy
Version: 1.1
Version: 1.2
## Purpose
Определяет когда писать тесты, когда не писать, и как их поддерживать.
Применяется ко всем проектам на Go. Агенты следуют этим правилам самостоятельно, без запроса подтверждения.
---
Применяется ко всем проектам на Go. Агенты следуют этим правилам самостоятельно,
без запроса подтверждения. See `README.md` for a reference table test.
## Когда тест обязателен
@@ -24,11 +23,9 @@ Version: 1.1
Для local-first desktop приложений правила деградированных состояний и recovery-тестов определяются также `local-first-recovery` contract.
---
## Когда тест не нужен
Тест не пишется на код, где он не даёт ценности:
Тест не пишется на код, где он не даёт ценности. Не писать его и не упоминать его отсутствие:
- Геттеры и сеттеры: `func (s *Server) Port() int { return s.port }`
- Конфиг-структуры и константы
@@ -36,50 +33,15 @@ Version: 1.1
- Логирование и форматирование вывода
- HTTP-хендлеры без бизнес-логики (только роутинг и вызов сервиса)
---
## Структура теста
Использовать стандартный Go `testing`. Табличные тесты (`[]struct{ ... }`) — когда случаев больше двух.
```go
func TestParseGPUSensor(t *testing.T) {
tests := []struct {
name string
xml string
want int
}{
{"normal", `<VALUE>290</VALUE>`, 29},
{"zero", `<VALUE>0</VALUE>`, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := parseGPUTemp(tt.xml)
if got != tt.want {
t.Fatalf("got %d, want %d", got, tt.want)
}
})
}
}
```
Фикстуры (XML, JSON, бинарные данные) — инлайн-константы или файлы в `testdata/`.
Не использовать реальные сетевые вызовы и реальную БД в юнит-тестах.
---
- Стандартный Go `testing`. Табличные тесты (`[]struct{ ... }`) — когда случаев больше двух.
- Фикстуры (XML, JSON, бинарные данные) — инлайн-константы или файлы в `testdata/`.
- Не использовать реальные сетевые вызовы и реальную БД в юнит-тестах.
## Мейнтейнс
- Сломанный тест — чинится или удаляется в том же коммите где сломался.
- Закомментированный тест — не допускается. Если тест неактуален — удалить.
- Тест, проверяющий удалённую функциональность — удалить вместе с функциональностью.
---
## Инструкция для агентов (Codex, Claude)
1. При добавлении функциональности — проверь по списку выше, попадает ли код в категорию "обязателен".
2. Если да — напиши тест в том же коммите, без запроса подтверждения.
3. Если нет — не пиши тест, не упоминай его отсутствие.
4. При удалении функциональности — удали соответствующие тесты.
5. При обнаружении закомментированных или сломанных тестов — удали или почини.
- При удалении функциональности — удалить соответствующие тесты в том же коммите.