Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/_TOC.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Table of Contents

1. [Quick Reference Card](quick-reference-card.md)
2. [Project overview](project-overview.md)
2. [JVM project requirements](jvm-project.md) — language, build, and review checklist shared by all JVM repos
3. [Coding guidelines](coding-guidelines.md)
4. [Documentation & comments](documentation-guidelines.md)
5. [Documentation tasks](documentation-tasks.md)
Expand Down
2 changes: 2 additions & 0 deletions .agents/coding-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
- **Generic parameters** over explicit variable types (`val list = mutableList<Dependency>()`)
- **Java interop annotations** only when needed (`@file:JvmName`, `@JvmStatic`)
- **Kotlin DSL** for Gradle files
- **Kotlin Protobuf DSL** (`myMessage { field = value }`) over Java builder chains

### ❌ Avoid
- Mutable data structures
- Java-style verbosity (builders with setters)
- Java Protobuf builders in Kotlin code (`newBuilder()`, `toBuilder()`) unless interop requires them
- Redundant null checks (`?.let` misuse)
- Using `!!` unless clearly justified
- Type names in variable names (`userObject`, `itemList`)
Expand Down
5 changes: 5 additions & 0 deletions .agents/documentation-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
- When using TODO comments, follow the format on the [dedicated page][todo-comments].
- File and directory names should be formatted as code.

## Protobuf file headers
- In `.proto` files, a multi-paragraph documentation header must end with a
trailing empty comment line (`//`).
- Single-paragraph headers do not require the trailing empty comment line.

## Avoid widows, runts, orphans, or rivers

Agents should **AVOID** text flow patters illustrated
Expand Down
37 changes: 37 additions & 0 deletions .agents/jvm-project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# JVM Project Requirements

General requirements for all JVM projects in the Spine SDK organisation.
Repo-specific `project.md` files link here and add their own context.

## Language and build

- **Languages**: Kotlin (primary), Java (secondary).
- **Build**: Gradle with Kotlin DSL.
- **Static analysis**: detekt, ErrorProne, Checkstyle, PMD.
- **Testing**: JUnit 5, Kotest Assertions, Codecov.

## Code review checklist

**Correctness and safety**
- Code compiles and passes static analysis (detekt, ErrorProne, Checkstyle, PMD).
- No reflection or unsafe code unless explicitly approved in scope.
- No analytics, telemetry, or tracking code.
- No blocking calls inside coroutines.

**Kotlin/Java style**
- Kotlin idioms preferred: extension functions, `when` expressions, data/sealed
classes, immutable data structures.
- No `!!` unless provably safe. No unchecked casts.
- No mutable state without justification.
- No string duplication — use constants.

**Tests**
- New or changed functionality must include tests.
- Use stubs, not mocks.
- Prefer [Kotest assertions][kotest-assertions] over JUnit or Google Truth.

**Versioning**
- If the repo has `version.gradle.kts`, every PR must include a version bump.
Flag the absence as a required change.

[kotest-assertions]: https://kotest.io/docs/assertions/assertions.html
5 changes: 3 additions & 2 deletions .agents/memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ See [README.md](README.md) for the format and routing rules.

## Feedback (validated patterns & corrections)

*(no entries yet)*
- [copilot-review-request](feedback/copilot-review-request.md) — GraphQL `requestReviews` with `botIds: ["BOT_kgDOCnlnWA"]`; REST endpoint silently no-ops on re-requests.

## Project (durable context & rationale)

*(no entries yet)*

## Reference (external systems)

*(no entries yet)*
- [cache-warm-window](reference/cache-warm-window.md) — How prompt cache entries are shared between sibling-repo sessions and how to maximise overlap.
- [anthropic-api-caching](reference/anthropic-api-caching.md) — Pattern and pricing for adding prompt caching to any direct Anthropic API call.
35 changes: 35 additions & 0 deletions .agents/memory/feedback/copilot-review-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: copilot-review-request
description: How to request or re-request a Copilot PR review programmatically — GraphQL botIds is the only reliable path
metadata:
type: feedback
since: 2026-05-25
---

Use the GraphQL `requestReviews` mutation with `botIds` for both initial
requests and re-requests:

```bash
gh api graphql -f query='
mutation {
requestReviews(input: {
pullRequestId: "PR_NODE_ID",
botIds: ["BOT_kgDOCnlnWA"]
}) {
pullRequest { id number }
}
}'
```

- `PR_NODE_ID`: `gh api repos/SpineEventEngine/REPO/pulls/NUMBER --jq '.node_id'`
- `BOT_kgDOCnlnWA`: fixed node ID for the Copilot PR reviewer bot (stable)

**Why:** The REST endpoint (`POST .../requested_reviewers` with
`reviewers[]=Copilot`) silently no-ops on re-requests — it only works for
the first-ever request on a PR. The GraphQL `userIds` field also fails
because Copilot is a Bot, not a User. `botIds` is the correct field and
works for both initial and re-requests.

**How to apply:** Any time a Copilot review needs to be requested or
re-requested, use the GraphQL mutation above. Do not use the REST endpoint
or `@copilot review` comments.
52 changes: 52 additions & 0 deletions .agents/memory/reference/anthropic-api-caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
name: anthropic-api-caching
description: Pattern and pricing for adding prompt caching to any direct Anthropic API call.
metadata:
type: reference
since: 2026-05-24
---

Use this when adding a direct Anthropic API call (GitHub Actions workflow,
script, or tool) that sends a stable system prompt.

**Add `cache_control` to the system message block:**

```python
system=[{
"type": "text",
"text": "<stable system prompt — skill definition, shared instructions, etc.>",
"cache_control": {"type": "ephemeral", "ttl": "1h"}
}]
```

Use `ttl: "1h"` for any caller whose requests are spaced more than 5 minutes
apart (GitHub Actions jobs, scheduled tasks, skill invocations). Use the
default 5-minute TTL only for tight interactive loops.

**Pricing (input tokens):**

| Operation | Cost multiplier |
|---|---|
| Cache write (5-min TTL) | 1.25× base input price |
| Cache write (1-hour TTL) | 2× base input price |
| Cache read (any TTL) | 0.1× base input price |

A single cache hit within the TTL window recovers the write premium. Multiple
hits within the hour make the 2× write cost negligible.

**Place stable content before dynamic content.** Cache breakpoints apply to
everything *before* the `cache_control` marker. Dynamic per-request content
(user query, file diff, current date) must come after the last breakpoint.

**Monitor hits via the usage object:**
```python
print(response.usage.cache_read_input_tokens) # 0 on miss, >0 on hit
print(response.usage.cache_creation_input_tokens) # tokens written to cache
```

**Future:** once direct API calls exist in this org, consider a cache pre-warm
job triggered on push to `master` — calls the API with `max_tokens: 0` and
`cache_control: {ttl: "1h"}` so the first session after a config change
hits rather than writes.

Related: [[cache-warm-window]]
33 changes: 33 additions & 0 deletions .agents/memory/reference/cache-warm-window.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: cache-warm-window
description: How prompt cache entries are shared between sibling-repo sessions and how to maximise overlap.
metadata:
type: reference
since: 2026-05-24
---

Claude Code sessions share a prompt cache entry when they send byte-identical
content within the cache TTL window. Because `migrate` copies `CLAUDE.md` and
`.agents/` verbatim, any two sessions on the same config version share the
same cache slot — provided they fall within the TTL.

**TTL in effect for Console OAuth users:**
- Default: **5 minutes** (applies to all non-subscription auth)
- With `ENABLE_PROMPT_CACHING_1H=1` in `~/.claude/settings.json`: **1 hour**

Developers must have `ENABLE_PROMPT_CACHING_1H=1` set, otherwise the
window is too short for cross-session hits to occur reliably.
This setting will work ONLY for Claude Code which runs the CLI binary.
It will not work for JetBrains Air or any other IDE plugin which does not
run the Claude Code CLI binary.

**Cache is per Anthropic workspace.** All developers authenticated via the
same Anthropic organisation Console org share the same cache pool. Do not
create separate Console workspaces per developer — that would isolate their
cache entries.

**Practical impact:** Realistic concurrency is 1–2 sessions at a time. The
first session after a config change pays the cache-write cost; any session
starting within the next hour (with 1H TTL) reads from cache at 0.1× cost.

Related: [[anthropic-api-caching]]
7 changes: 0 additions & 7 deletions .agents/project-overview.md

This file was deleted.

38 changes: 38 additions & 0 deletions .agents/project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Project: base-libraries

## Overview

`base-libraries` is a foundational JVM repository in the Spine SDK organisation.
It hosts the common data types, annotations, environment helpers, and
parsing/serialization utilities that the rest of the Spine SDK (notably
[`core-jvm`](https://github.com/SpineEventEngine/core-java)) depends on. The
artifacts published from this repo sit at the bottom of the Spine dependency
graph, so changes here ripple into most other Spine projects.

## Architecture

Role: **library** (multi-module Gradle build) publishing the following Maven
artifacts under the `io.spine` group:

- `annotations` — annotation types used across the Spine SDK.
- `base` — common data types and utilities. Not consumed directly by
end users; re-exposed as an `api` dependency by `spine-client` and
`spine-server` in `core-jvm`.
- `environment` — runtime environment detection helpers.
- `format` — parsers for YAML, JSON, binary Protobuf, and Protobuf JSON;
used internally by Spine SDK components.

Key constraints:

- Public API stability matters: downstream Spine repos pin to versions
published from here, so removals and signature changes are breaking.
- No analytics, telemetry, reflection, or unsafe code (see
`.agents/safety-rules.md`).
- Versioning follows the Spine SDK policy (`.agents/version-policy.md`);
CI's `Version Guard` rejects branches that reuse a published version.
- Dependency declarations live under
`buildSrc/src/main/kotlin/io/spine/dependency/` and are audited by the
`dependency-audit` skill.

Read [`.agents/jvm-project.md`](jvm-project.md) for build stack, coding
style, tests, and versioning.
18 changes: 18 additions & 0 deletions .agents/project.template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!-- Template — copy to a sibling repo's .agents/project.md and fill in the
sections below. In the config repo itself this file is a template only. -->

# Project: <name>

## Overview

*One paragraph: what this repo is, what problem it solves, and its role in the
Spine SDK organisation.*

## Architecture

*Role in the org: library / tool / Gradle plugin / application.
Key patterns, public API boundaries, and constraints specific to this repo.*

<!-- JVM projects: uncomment the line below after seeding this file.
Read [`.agents/jvm-project.md`](jvm-project.md) for build stack, coding style, tests, and versioning.
-->
12 changes: 5 additions & 7 deletions .agents/quick-reference-card.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# 📝 Quick Reference Card

```
🔑 Key Information:
- Kotlin/Java project with CQRS architecture
- Follow coding guidelines in Spine Event Engine docs
- Always include tests with code changes
- Version bump required for all PRs
```
🚫 **Do not write to git history** (commit/push/tag/rebase/merge/cherry-pick/reset/`gh pr merge`) without explicit authorization. See
[`safety-rules.md`](safety-rules.md) → *Commits and history-writing*.
Authorization comes only from a skill's `## Commit authorization`
section or from the user's current prompt — never from prior turns or
memory.
42 changes: 42 additions & 0 deletions .agents/safety-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,45 @@
- ❌ Never use reflection or unsafe code without an explicit approval.
- ❌ No analytics or telemetry code.
- ❌ No blocking calls inside coroutines.

## Commits and history-writing

**Default: do not write to git history.** This is a hard rule for every
agent — the main thread, every subagent, every skill. It overrides any
local convenience or "the change looks done" instinct.

The rule covers all of these operations:

- `git commit`, `git commit-tree`
- `git push`, `git push --force`
- `git tag`
- `git rebase`, `git merge`, `git cherry-pick` against shared history
- `git reset` that discards committed work
- `gh release create`, `gh pr merge`

Authorization to perform one of these operations exists only when **one**
of the following is true *right now*:

1. **Skill-declared.** The currently active skill's `SKILL.md` contains
a `## Commit authorization` section that explicitly authorizes the
operation and constrains it (which files may be staged, the exact
commit subject, the maximum number of commits). The mere mention of
a commit message inside skill prose is **not** authorization — the
section heading must be present.
2. **User-instructed.** The user's *current* prompt explicitly tells
the agent to perform the operation. Examples that qualify:
"commit this", "make a commit with subject X", "push the branch",
"tag this release". Authorization from previous turns, from
`CLAUDE.md`, or from any memory file does **not** carry over.

If neither holds, the agent:

1. Stages relevant changes with `git add` (only if helpful for review).
2. Prints the proposed commit subject (if any) and `git diff --staged`.
3. **Stops.** The user runs the commit themselves, or replies with
explicit authorization in the next prompt.

The project's `.claude/settings.json` keeps `Bash(git commit:*)` in
`permissions.ask` as defense-in-depth, but the primary enforcement is
this rule — agents must not propose commit attempts that rely on the
user clicking the prompt.
3 changes: 3 additions & 0 deletions .agents/scripts/api-discovery/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Per-developer override of <workspace-root> for the api-discovery
# extraction cache. Contains an absolute path; do not commit.
.workspace-root
Loading
Loading