Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c6c4f1e1e | ||
|
|
e8521c2555 | ||
|
|
e696db2e68 |
+16
-4
@@ -37,9 +37,9 @@
|
|||||||
|
|
||||||
### Git
|
### Git
|
||||||
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
||||||
- **Trunk-Based Development:** commit directly to main. One logical change per commit.
|
- **Trunk-Based Development:** one logical change per commit, merged to main by PR (`main` is protected, see below).
|
||||||
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
||||||
- No feature branches, no PRs for solo/agent work.
|
- Short-lived branches and PRs are how work reaches `main` here (`tbd_ship`/`pr_merge`); no long-lived feature branches.
|
||||||
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
||||||
`agent/<description>` branch and merge within the same session.
|
`agent/<description>` branch and merge within the same session.
|
||||||
|
|
||||||
@@ -79,8 +79,8 @@ When acting as a coding agent on this project:
|
|||||||
3. If unsure about a convention, check `DECISIONS.md` or ask
|
3. If unsure about a convention, check `DECISIONS.md` or ask
|
||||||
4. Never modify files outside the project root without explicit permission
|
4. Never modify files outside the project root without explicit permission
|
||||||
5. When adding a dependency, explain why in the commit message
|
5. When adding a dependency, explain why in the commit message
|
||||||
6. Commit directly to main. Run `task check` before every push. Never create
|
6. Ship by PR (`main` is protected, see below). Run `task check` before every push. Never create
|
||||||
feature branches unless a parallel agent is simultaneously active on this repo.
|
long-lived feature branches.
|
||||||
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
||||||
|
|
||||||
## Current state — v0.2.5 (2026-05-17)
|
## Current state — v0.2.5 (2026-05-17)
|
||||||
@@ -105,3 +105,15 @@ Current main: `e31fd3f`. CI green. Deployed via Flux.
|
|||||||
|
|
||||||
2. **Issue #19** — end-to-end mirror flow verification.
|
2. **Issue #19** — end-to-end mirror flow verification.
|
||||||
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
||||||
|
|
||||||
|
## `main` is protected: ship by PR (local-dev#42, decided 2026-10-08)
|
||||||
|
|
||||||
|
Gitea refuses direct pushes to `main` in this repo, and a PR merges only after its CI status (`CD / Lint / Test / Vet (pull_request)`) passes.
|
||||||
|
**Why:** local-dev rule 5's reviewed lane (risk/medium+ is reviewed by a human) was enforced on the merge tools
|
||||||
|
(`tbd_ship`, `pr_merge`: gitea-mcp v0.17.0/v0.18.0, merge only for an issue labelled exactly `risk/low` with green CI)
|
||||||
|
but not on a direct commit to `main`, which bypassed it. This overrides rule 5's "risk/low commits straight to main"
|
||||||
|
for this repo; control code is where the lane matters.
|
||||||
|
**How:** `tbd_ship` for a one-file change, or branch -> PR -> `pr_merge` (name the `risk/low` issue); above `risk/low`
|
||||||
|
open the PR and a human merges it in the Gitea UI after review. Tags are not protected. CD jobs push image tags to
|
||||||
|
the **infra** repo with deploy keys, never to this repo's `main`. Undo (Mathias only): Settings -> Branches, or
|
||||||
|
`PATCH /repos/mathias/gitea-mcp/branch_protections/main {"enable_push": true}`.
|
||||||
|
|||||||
+85
-21
@@ -164,6 +164,63 @@ These rules apply to every task across every project, regardless of harness.
|
|||||||
the thing it was named for was exploitable. If you cannot name the mechanism,
|
the thing it was named for was exploitable. If you cannot name the mechanism,
|
||||||
you do not yet know what the test observes.
|
you do not yet know what the test observes.
|
||||||
|
|
||||||
|
10. **Short sessions, one rc per repo, edit only in a locked worktree of the repo
|
||||||
|
you are changing** (ADR-0002, accepted 2026-10-06).
|
||||||
|
- One session per issue or task, ending with rule 6's close ritual. Related
|
||||||
|
issues may share a session only when they share a worktree and an owner.
|
||||||
|
State that must outlive the session goes in an issue, not the chat.
|
||||||
|
- Start `claude rc` in the repo you will edit (`infra`, `trucker-ecommerce`,
|
||||||
|
`hyperguild`, ...), not in `~/dev`: the rc worktree is a worktree of the
|
||||||
|
launch directory's repo, so launched from `~/dev` it protects nothing you
|
||||||
|
edit (measured: 73% of edits landed in shared checkouts). Start it only
|
||||||
|
while working there.
|
||||||
|
- Keep at most one thin `~/dev` coordinator session. It files issues and hands
|
||||||
|
out tasks; it reads and edits no sub-repo code.
|
||||||
|
- Split cross-repo work per repo. The contract between the halves lives in an
|
||||||
|
issue on each repo.
|
||||||
|
- Edit in a worktree of that repo, locked at creation:
|
||||||
|
`scripts/wt.sh add <repo> <task>` does it (fetch, `wt/<task>` from origin/main, lock);
|
||||||
|
`scripts/wt.sh done <repo>-<task>` removes it after the push and refuses dirty or
|
||||||
|
unpushed work. By hand: `git worktree add ~/worktrees/<name> -b <branch> origin/main`
|
||||||
|
then `git worktree lock --reason "manual: <purpose>" ~/worktrees/<name>`.
|
||||||
|
- Before working a repo another session may touch, announce your issue list to
|
||||||
|
that session (`SendMessage`) and ask for theirs.
|
||||||
|
- Auto-memory is keyed by cwd, so a repo rc starts without it. Cross-repo
|
||||||
|
working rules live in brain (`wiki/homelab/decisions/2026-10-06-062416-auto.md`, wing homelab, hall
|
||||||
|
decisions) and the section below, not in per-directory memory.
|
||||||
|
|
||||||
|
## Standing footguns
|
||||||
|
|
||||||
|
Each cost real time once. Detail and evidence: brain `wiki/homelab/decisions/2026-10-06-062416-auto.md` (title standing-working-rules).
|
||||||
|
|
||||||
|
- **Gate then commit with `&&`, never `;`.** "Green" means exit code 0 and
|
||||||
|
`grep -c FAIL` is 0, not a filtered grep.
|
||||||
|
- **Stage by path, never `git add -A` or `git add .`** (they stage from the repo
|
||||||
|
root and swept in other sessions' work twice). Check `git status --porcelain` first.
|
||||||
|
- **Before committing in a shared checkout:** `git branch --show-current`.
|
||||||
|
- **Before tagging:** `git fetch origin --tags`, then `git describe --tags --abbrev=0 <sha>`
|
||||||
|
and `git tag --sort=-v:refname | head`; go above both. Never take the last tag
|
||||||
|
from a report.
|
||||||
|
- **Run only what the project's gate runs.** No repo-wide formatter unless the gate
|
||||||
|
runs it.
|
||||||
|
- **Reproduce a CI red at the cited commit before applying an issue's prescribed fix.**
|
||||||
|
- **Read an issue's comments (`issue_list_comments`), not just its body, before working it.**
|
||||||
|
- **A comment naming a control ("behind branch protection") is not evidence; query
|
||||||
|
the control.** A working detector can hide a missing preventer.
|
||||||
|
- **On koala the MCP servers are `mcp__plugin_skills_{brain,gitea,infra}__*`.** The
|
||||||
|
per-turn auth reminder is not evidence; call the tool or run `claude mcp list`.
|
||||||
|
Brain writes always pass `wing` + `hall`.
|
||||||
|
- **`cat /etc/hostname` before assuming which host you are on.**
|
||||||
|
- **Never run bare `git remote -v` or `git config --list`** (url.insteadOf expands
|
||||||
|
into a live token); use `git config --get remote.origin.url`.
|
||||||
|
- **On koala `sudo` is denied outright; k8s exec, env dumps and flux reconcile need
|
||||||
|
per-action approval; decrypting a SOPS file and printing in one Bash call is
|
||||||
|
hook-blocked.** Do the repo-side work and hand the host-side step over in an issue.
|
||||||
|
- **`set -o pipefail` plus an optional `grep | head | awk` dies on no match:** append `|| true`.
|
||||||
|
- **Gitea `file_write_branch` takes plain text, not base64.**
|
||||||
|
- **`OP_SERVICE_ACCOUNT_TOKEN` in the shell is read-only for `op`.** Operational
|
||||||
|
secrets go in the AgentSecrets vault via `set -a; . ~/.op-agent-write.env; set +a`.
|
||||||
|
|
||||||
## CAD sprint patterns
|
## CAD sprint patterns
|
||||||
|
|
||||||
Two CAD sprint archetypes (defs: brain `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16`):
|
Two CAD sprint archetypes (defs: brain `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16`):
|
||||||
@@ -244,25 +301,20 @@ Three machines on Tailscale:
|
|||||||
|
|
||||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||||
|
|
||||||
Organized in thematic folders:
|
Organized by **role**, because the role decides which rules apply (ADR-0003):
|
||||||
|
|
||||||
| Folder | Focus | Count |
|
| Folder | Role | Rules that key off it |
|
||||||
|--------|-------|-------|
|
|--------|------|-----------------------|
|
||||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
| `platform/` | infra, brain, hyperguild, gitea-mcp, dispatch, shared tooling | control code (rule 8), GitOps review lane |
|
||||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
| `products/` | tapir, cobalt-dingo, openbanking-api, ... | ordinary trunk-based work |
|
||||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
| `clients/` | client work | local models only, never cloud APIs (Client work rules) |
|
||||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
| `spikes/` | throwaway | no ceremony |
|
||||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
|
||||||
|
|
||||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
New projects are born into a role folder (`task new-project -- <name> <client|personal>
|
||||||
|
<role-folder>`); a client tag requires `clients/` and `clients/` requires a client tag.
|
||||||
### Key active projects
|
Existing repos still sit in the old `AGENTS/` and `AI/` folders until they are moved one by
|
||||||
|
one (ADR-0003 step 3). `~/dev/PROJECT_SUMMARY.md` (generated) lists every repo and where it
|
||||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
is. How a session runs on koala (worktrees, rc per repo, the reaper, memory): `docs/working-on-koala.md`.
|
||||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
|
||||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
|
||||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
|
||||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
|
||||||
|
|
||||||
## Knowledge base — actively use it
|
## Knowledge base — actively use it
|
||||||
|
|
||||||
@@ -466,9 +518,9 @@ Check a host with `task doctor` in the skills repo; it also runs automatically a
|
|||||||
|
|
||||||
### Git
|
### Git
|
||||||
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
||||||
- **Trunk-Based Development:** commit directly to main. One logical change per commit.
|
- **Trunk-Based Development:** one logical change per commit, merged to main by PR (`main` is protected, see below).
|
||||||
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
||||||
- No feature branches, no PRs for solo/agent work.
|
- Short-lived branches and PRs are how work reaches `main` here (`tbd_ship`/`pr_merge`); no long-lived feature branches.
|
||||||
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
||||||
`agent/<description>` branch and merge within the same session.
|
`agent/<description>` branch and merge within the same session.
|
||||||
|
|
||||||
@@ -508,8 +560,8 @@ When acting as a coding agent on this project:
|
|||||||
3. If unsure about a convention, check `DECISIONS.md` or ask
|
3. If unsure about a convention, check `DECISIONS.md` or ask
|
||||||
4. Never modify files outside the project root without explicit permission
|
4. Never modify files outside the project root without explicit permission
|
||||||
5. When adding a dependency, explain why in the commit message
|
5. When adding a dependency, explain why in the commit message
|
||||||
6. Commit directly to main. Run `task check` before every push. Never create
|
6. Ship by PR (`main` is protected, see below). Run `task check` before every push. Never create
|
||||||
feature branches unless a parallel agent is simultaneously active on this repo.
|
long-lived feature branches.
|
||||||
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
||||||
|
|
||||||
## Current state — v0.2.5 (2026-05-17)
|
## Current state — v0.2.5 (2026-05-17)
|
||||||
@@ -535,4 +587,16 @@ Current main: `e31fd3f`. CI green. Deployed via Flux.
|
|||||||
2. **Issue #19** — end-to-end mirror flow verification.
|
2. **Issue #19** — end-to-end mirror flow verification.
|
||||||
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
||||||
|
|
||||||
|
## `main` is protected: ship by PR (local-dev#42, decided 2026-10-08)
|
||||||
|
|
||||||
|
Gitea refuses direct pushes to `main` in this repo, and a PR merges only after its CI status (`CD / Lint / Test / Vet (pull_request)`) passes.
|
||||||
|
**Why:** local-dev rule 5's reviewed lane (risk/medium+ is reviewed by a human) was enforced on the merge tools
|
||||||
|
(`tbd_ship`, `pr_merge`: gitea-mcp v0.17.0/v0.18.0, merge only for an issue labelled exactly `risk/low` with green CI)
|
||||||
|
but not on a direct commit to `main`, which bypassed it. This overrides rule 5's "risk/low commits straight to main"
|
||||||
|
for this repo; control code is where the lane matters.
|
||||||
|
**How:** `tbd_ship` for a one-file change, or branch -> PR -> `pr_merge` (name the `risk/low` issue); above `risk/low`
|
||||||
|
open the PR and a human merges it in the Gitea UI after review. Tags are not protected. CD jobs push image tags to
|
||||||
|
the **infra** repo with deploy keys, never to this repo's `main`. Undo (Mathias only): Settings -> Branches, or
|
||||||
|
`PATCH /repos/mathias/gitea-mcp/branch_protections/main {"enable_push": true}`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -159,6 +159,63 @@ These rules apply to every task across every project, regardless of harness.
|
|||||||
the thing it was named for was exploitable. If you cannot name the mechanism,
|
the thing it was named for was exploitable. If you cannot name the mechanism,
|
||||||
you do not yet know what the test observes.
|
you do not yet know what the test observes.
|
||||||
|
|
||||||
|
10. **Short sessions, one rc per repo, edit only in a locked worktree of the repo
|
||||||
|
you are changing** (ADR-0002, accepted 2026-10-06).
|
||||||
|
- One session per issue or task, ending with rule 6's close ritual. Related
|
||||||
|
issues may share a session only when they share a worktree and an owner.
|
||||||
|
State that must outlive the session goes in an issue, not the chat.
|
||||||
|
- Start `claude rc` in the repo you will edit (`infra`, `trucker-ecommerce`,
|
||||||
|
`hyperguild`, ...), not in `~/dev`: the rc worktree is a worktree of the
|
||||||
|
launch directory's repo, so launched from `~/dev` it protects nothing you
|
||||||
|
edit (measured: 73% of edits landed in shared checkouts). Start it only
|
||||||
|
while working there.
|
||||||
|
- Keep at most one thin `~/dev` coordinator session. It files issues and hands
|
||||||
|
out tasks; it reads and edits no sub-repo code.
|
||||||
|
- Split cross-repo work per repo. The contract between the halves lives in an
|
||||||
|
issue on each repo.
|
||||||
|
- Edit in a worktree of that repo, locked at creation:
|
||||||
|
`scripts/wt.sh add <repo> <task>` does it (fetch, `wt/<task>` from origin/main, lock);
|
||||||
|
`scripts/wt.sh done <repo>-<task>` removes it after the push and refuses dirty or
|
||||||
|
unpushed work. By hand: `git worktree add ~/worktrees/<name> -b <branch> origin/main`
|
||||||
|
then `git worktree lock --reason "manual: <purpose>" ~/worktrees/<name>`.
|
||||||
|
- Before working a repo another session may touch, announce your issue list to
|
||||||
|
that session (`SendMessage`) and ask for theirs.
|
||||||
|
- Auto-memory is keyed by cwd, so a repo rc starts without it. Cross-repo
|
||||||
|
working rules live in brain (`wiki/homelab/decisions/2026-10-06-062416-auto.md`, wing homelab, hall
|
||||||
|
decisions) and the section below, not in per-directory memory.
|
||||||
|
|
||||||
|
## Standing footguns
|
||||||
|
|
||||||
|
Each cost real time once. Detail and evidence: brain `wiki/homelab/decisions/2026-10-06-062416-auto.md` (title standing-working-rules).
|
||||||
|
|
||||||
|
- **Gate then commit with `&&`, never `;`.** "Green" means exit code 0 and
|
||||||
|
`grep -c FAIL` is 0, not a filtered grep.
|
||||||
|
- **Stage by path, never `git add -A` or `git add .`** (they stage from the repo
|
||||||
|
root and swept in other sessions' work twice). Check `git status --porcelain` first.
|
||||||
|
- **Before committing in a shared checkout:** `git branch --show-current`.
|
||||||
|
- **Before tagging:** `git fetch origin --tags`, then `git describe --tags --abbrev=0 <sha>`
|
||||||
|
and `git tag --sort=-v:refname | head`; go above both. Never take the last tag
|
||||||
|
from a report.
|
||||||
|
- **Run only what the project's gate runs.** No repo-wide formatter unless the gate
|
||||||
|
runs it.
|
||||||
|
- **Reproduce a CI red at the cited commit before applying an issue's prescribed fix.**
|
||||||
|
- **Read an issue's comments (`issue_list_comments`), not just its body, before working it.**
|
||||||
|
- **A comment naming a control ("behind branch protection") is not evidence; query
|
||||||
|
the control.** A working detector can hide a missing preventer.
|
||||||
|
- **On koala the MCP servers are `mcp__plugin_skills_{brain,gitea,infra}__*`.** The
|
||||||
|
per-turn auth reminder is not evidence; call the tool or run `claude mcp list`.
|
||||||
|
Brain writes always pass `wing` + `hall`.
|
||||||
|
- **`cat /etc/hostname` before assuming which host you are on.**
|
||||||
|
- **Never run bare `git remote -v` or `git config --list`** (url.insteadOf expands
|
||||||
|
into a live token); use `git config --get remote.origin.url`.
|
||||||
|
- **On koala `sudo` is denied outright; k8s exec, env dumps and flux reconcile need
|
||||||
|
per-action approval; decrypting a SOPS file and printing in one Bash call is
|
||||||
|
hook-blocked.** Do the repo-side work and hand the host-side step over in an issue.
|
||||||
|
- **`set -o pipefail` plus an optional `grep | head | awk` dies on no match:** append `|| true`.
|
||||||
|
- **Gitea `file_write_branch` takes plain text, not base64.**
|
||||||
|
- **`OP_SERVICE_ACCOUNT_TOKEN` in the shell is read-only for `op`.** Operational
|
||||||
|
secrets go in the AgentSecrets vault via `set -a; . ~/.op-agent-write.env; set +a`.
|
||||||
|
|
||||||
## CAD sprint patterns
|
## CAD sprint patterns
|
||||||
|
|
||||||
Two CAD sprint archetypes (defs: brain `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16`):
|
Two CAD sprint archetypes (defs: brain `wiki/homelab/decisions/continuous-agentic-development-cad-concept-2026-06-16`):
|
||||||
@@ -239,25 +296,20 @@ Three machines on Tailscale:
|
|||||||
|
|
||||||
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
All development repos live at `~/dev/` (softlink from `~/Documents/local-dev/`).
|
||||||
|
|
||||||
Organized in thematic folders:
|
Organized by **role**, because the role decides which rules apply (ADR-0003):
|
||||||
|
|
||||||
| Folder | Focus | Count |
|
| Folder | Role | Rules that key off it |
|
||||||
|--------|-------|-------|
|
|--------|------|-----------------------|
|
||||||
| `GO/` | Go web frameworks, API integrations, learning projects | ~10 |
|
| `platform/` | infra, brain, hyperguild, gitea-mcp, dispatch, shared tooling | control code (rule 8), GitOps review lane |
|
||||||
| `AI/` | ML research, AI frameworks (FinRL, DSPy, crawl4ai) | ~6 |
|
| `products/` | tapir, cobalt-dingo, openbanking-api, ... | ordinary trunk-based work |
|
||||||
| `AGENTS/` | Autonomous agents, coding agents, MCP servers, infra | ~15 |
|
| `clients/` | client work | local models only, never cloud APIs (Client work rules) |
|
||||||
| `QKX/` | Invoice processing, financial automation, payment systems | ~13 |
|
| `spikes/` | throwaway | no ceremony |
|
||||||
| `XT/` | Climate data, sustainability (Klimatkollen, Garbo) | ~2 |
|
|
||||||
|
|
||||||
See `~/dev/PROJECT_SUMMARY.md` for detailed descriptions of each project.
|
New projects are born into a role folder (`task new-project -- <name> <client|personal>
|
||||||
|
<role-folder>`); a client tag requires `clients/` and `clients/` requires a client tag.
|
||||||
### Key active projects
|
Existing repos still sit in the old `AGENTS/` and `AI/` folders until they are moved one by
|
||||||
|
one (ADR-0003 step 3). `~/dev/PROJECT_SUMMARY.md` (generated) lists every repo and where it
|
||||||
- **super-koala** (`AGENTS/`) — multi-component agent stack with LangGraph, DSPy, MCP
|
is. How a session runs on koala (worktrees, rc per repo, the reaper, memory): `docs/working-on-koala.md`.
|
||||||
- **azure-tiger** (`QKX/`) — invoice extraction → ISO 20022 payment instructions
|
|
||||||
- **gocrwl** (`AGENTS/`) — Go web crawler with containerized deployment
|
|
||||||
- **koala-ai-stack** (`AGENTS/`) — local AI server infrastructure management
|
|
||||||
- **klimatkollen** (`XT/`) — Swedish municipal climate data platform
|
|
||||||
|
|
||||||
## Knowledge base — actively use it
|
## Knowledge base — actively use it
|
||||||
|
|
||||||
@@ -461,9 +513,9 @@ Check a host with `task doctor` in the skills repo; it also runs automatically a
|
|||||||
|
|
||||||
### Git
|
### Git
|
||||||
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
||||||
- **Trunk-Based Development:** commit directly to main. One logical change per commit.
|
- **Trunk-Based Development:** one logical change per commit, merged to main by PR (`main` is protected, see below).
|
||||||
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
||||||
- No feature branches, no PRs for solo/agent work.
|
- Short-lived branches and PRs are how work reaches `main` here (`tbd_ship`/`pr_merge`); no long-lived feature branches.
|
||||||
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
||||||
`agent/<description>` branch and merge within the same session.
|
`agent/<description>` branch and merge within the same session.
|
||||||
|
|
||||||
@@ -503,8 +555,8 @@ When acting as a coding agent on this project:
|
|||||||
3. If unsure about a convention, check `DECISIONS.md` or ask
|
3. If unsure about a convention, check `DECISIONS.md` or ask
|
||||||
4. Never modify files outside the project root without explicit permission
|
4. Never modify files outside the project root without explicit permission
|
||||||
5. When adding a dependency, explain why in the commit message
|
5. When adding a dependency, explain why in the commit message
|
||||||
6. Commit directly to main. Run `task check` before every push. Never create
|
6. Ship by PR (`main` is protected, see below). Run `task check` before every push. Never create
|
||||||
feature branches unless a parallel agent is simultaneously active on this repo.
|
long-lived feature branches.
|
||||||
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
||||||
|
|
||||||
## Current state — v0.2.5 (2026-05-17)
|
## Current state — v0.2.5 (2026-05-17)
|
||||||
@@ -529,3 +581,15 @@ Current main: `e31fd3f`. CI green. Deployed via Flux.
|
|||||||
|
|
||||||
2. **Issue #19** — end-to-end mirror flow verification.
|
2. **Issue #19** — end-to-end mirror flow verification.
|
||||||
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
||||||
|
|
||||||
|
## `main` is protected: ship by PR (local-dev#42, decided 2026-10-08)
|
||||||
|
|
||||||
|
Gitea refuses direct pushes to `main` in this repo, and a PR merges only after its CI status (`CD / Lint / Test / Vet (pull_request)`) passes.
|
||||||
|
**Why:** local-dev rule 5's reviewed lane (risk/medium+ is reviewed by a human) was enforced on the merge tools
|
||||||
|
(`tbd_ship`, `pr_merge`: gitea-mcp v0.17.0/v0.18.0, merge only for an issue labelled exactly `risk/low` with green CI)
|
||||||
|
but not on a direct commit to `main`, which bypassed it. This overrides rule 5's "risk/low commits straight to main"
|
||||||
|
for this repo; control code is where the lane matters.
|
||||||
|
**How:** `tbd_ship` for a one-file change, or branch -> PR -> `pr_merge` (name the `risk/low` issue); above `risk/low`
|
||||||
|
open the PR and a human merges it in the Gitea UI after review. Tags are not protected. CD jobs push image tags to
|
||||||
|
the **infra** repo with deploy keys, never to this repo's `main`. Undo (Mathias only): Settings -> Branches, or
|
||||||
|
`PATCH /repos/mathias/gitea-mcp/branch_protections/main {"enable_push": true}`.
|
||||||
|
|||||||
@@ -37,9 +37,9 @@
|
|||||||
|
|
||||||
### Git
|
### Git
|
||||||
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
- Conventional commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`
|
||||||
- **Trunk-Based Development:** commit directly to main. One logical change per commit.
|
- **Trunk-Based Development:** one logical change per commit, merged to main by PR (`main` is protected, see below).
|
||||||
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
- Run `task check` locally before every push. CI is the quality gate, not branch protection.
|
||||||
- No feature branches, no PRs for solo/agent work.
|
- Short-lived branches and PRs are how work reaches `main` here (`tbd_ship`/`pr_merge`); no long-lived feature branches.
|
||||||
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
- Exception: if a parallel agent session is active on this repo, use a short-lived
|
||||||
`agent/<description>` branch and merge within the same session.
|
`agent/<description>` branch and merge within the same session.
|
||||||
|
|
||||||
@@ -79,8 +79,8 @@ When acting as a coding agent on this project:
|
|||||||
3. If unsure about a convention, check `DECISIONS.md` or ask
|
3. If unsure about a convention, check `DECISIONS.md` or ask
|
||||||
4. Never modify files outside the project root without explicit permission
|
4. Never modify files outside the project root without explicit permission
|
||||||
5. When adding a dependency, explain why in the commit message
|
5. When adding a dependency, explain why in the commit message
|
||||||
6. Commit directly to main. Run `task check` before every push. Never create
|
6. Ship by PR (`main` is protected, see below). Run `task check` before every push. Never create
|
||||||
feature branches unless a parallel agent is simultaneously active on this repo.
|
long-lived feature branches.
|
||||||
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
7. For client projects: never send code or context to cloud APIs — use local models via LiteLLM
|
||||||
|
|
||||||
## Current state — v0.2.5 (2026-05-17)
|
## Current state — v0.2.5 (2026-05-17)
|
||||||
@@ -105,3 +105,15 @@ Current main: `e31fd3f`. CI green. Deployed via Flux.
|
|||||||
|
|
||||||
2. **Issue #19** — end-to-end mirror flow verification.
|
2. **Issue #19** — end-to-end mirror flow verification.
|
||||||
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
`repo_mirror_push` is implemented but the full flow (create repo → add push mirror → verify sync to GitHub) has not been tested manually. Do this before relying on it in production.
|
||||||
|
|
||||||
|
## `main` is protected: ship by PR (local-dev#42, decided 2026-10-08)
|
||||||
|
|
||||||
|
Gitea refuses direct pushes to `main` in this repo, and a PR merges only after its CI status (`CD / Lint / Test / Vet (pull_request)`) passes.
|
||||||
|
**Why:** local-dev rule 5's reviewed lane (risk/medium+ is reviewed by a human) was enforced on the merge tools
|
||||||
|
(`tbd_ship`, `pr_merge`: gitea-mcp v0.17.0/v0.18.0, merge only for an issue labelled exactly `risk/low` with green CI)
|
||||||
|
but not on a direct commit to `main`, which bypassed it. This overrides rule 5's "risk/low commits straight to main"
|
||||||
|
for this repo; control code is where the lane matters.
|
||||||
|
**How:** `tbd_ship` for a one-file change, or branch -> PR -> `pr_merge` (name the `risk/low` issue); above `risk/low`
|
||||||
|
open the PR and a human merges it in the Gitea UI after review. Tags are not protected. CD jobs push image tags to
|
||||||
|
the **infra** repo with deploy keys, never to this repo's `main`. Undo (Mathias only): Settings -> Branches, or
|
||||||
|
`PATCH /repos/mathias/gitea-mcp/branch_protections/main {"enable_push": true}`.
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func (c *Client) GetPullRequestDiff(ctx context.Context, owner, repo string, ind
|
|||||||
|
|
||||||
type MergePRArgs struct {
|
type MergePRArgs struct {
|
||||||
Do string `json:"Do"`
|
Do string `json:"Do"`
|
||||||
Title string `json:"merge_message_title,omitempty"`
|
Title string `json:"merge_title_field,omitempty"`
|
||||||
Body string `json:"merge_message_field,omitempty"`
|
Body string `json:"merge_message_field,omitempty"`
|
||||||
// HeadCommitID binds the merge to the commit whose CI was checked: if the PR branch moved, Gitea refuses.
|
// HeadCommitID binds the merge to the commit whose CI was checked: if the PR branch moved, Gitea refuses.
|
||||||
HeadCommitID string `json:"head_commit_id,omitempty"`
|
HeadCommitID string `json:"head_commit_id,omitempty"`
|
||||||
|
|||||||
@@ -166,6 +166,22 @@ func TestPRMergeDefaultsToMergeStyleAndPassesStyleThrough(t *testing.T) {
|
|||||||
assert.Equal(t, "squash", payload["Do"])
|
assert.Equal(t, "squash", payload["Do"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gitea 1.27's MergePullRequestOption has merge_title_field and merge_message_field. A field it does not know is
|
||||||
|
// ignored without an error, so a custom merge title silently did nothing while this tool sent merge_message_title
|
||||||
|
// (gitea-mcp#77). The tool's own argument keeps its name; the wire field must be Gitea's.
|
||||||
|
func TestPRMerge_ACustomMergeTitleTravelsAsGiteasMergeTitleField(t *testing.T) {
|
||||||
|
f := newPRMergeFake(t, prMergeFakeOpts{})
|
||||||
|
|
||||||
|
_, err := callMerge(t, f, `{"owner":"owner","repo":"repo","number":7,"issue":42,"merge_message_title":"feat: one line","merge_message_field":"body text"}`)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
var payload map[string]any
|
||||||
|
require.NoError(t, json.Unmarshal(f.mergeBody, &payload))
|
||||||
|
assert.Equal(t, "feat: one line", payload["merge_title_field"])
|
||||||
|
assert.Equal(t, "body text", payload["merge_message_field"])
|
||||||
|
assert.NotContains(t, payload, "merge_message_title", "not a Gitea field: it is ignored without an error")
|
||||||
|
}
|
||||||
|
|
||||||
// TOCTOU: the gate read CI for ONE head commit. The merge must be bound to that commit, so a push to the PR branch
|
// TOCTOU: the gate read CI for ONE head commit. The merge must be bound to that commit, so a push to the PR branch
|
||||||
// after the check makes Gitea refuse the merge instead of merging code nobody checked.
|
// after the check makes Gitea refuse the merge instead of merging code nobody checked.
|
||||||
func TestPRMerge_TheMergeIsBoundToTheCommitTheGateChecked(t *testing.T) {
|
func TestPRMerge_TheMergeIsBoundToTheCommitTheGateChecked(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user