Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6f78557
Add config as a Git submodule
alexander-yevsyukov May 25, 2026
42190b6
Rollback Gradle to 6.7.1
alexander-yevsyukov May 25, 2026
6e96cf0
Apply `config`
alexander-yevsyukov May 25, 2026
c7e2f42
Update Hugo modules of Documentation and Validation to latest versions
alexander-yevsyukov May 25, 2026
2f013c9
Fix XSS and race condition in OSS licenses page
alexander-yevsyukov May 25, 2026
1600a56
Update modules
alexander-yevsyukov May 25, 2026
74e36ad
Bump Gradle -> `6.9.4`
alexander-yevsyukov May 25, 2026
b4cdd76
Remove duplicating workflow
alexander-yevsyukov May 25, 2026
f999465
Remove irrelevant workflows
alexander-yevsyukov May 25, 2026
71c36da
Add project description for agents
alexander-yevsyukov May 25, 2026
7e225e4
Remove redundant submodules
alexander-yevsyukov May 25, 2026
8e421f8
Remove `_code` directory
alexander-yevsyukov May 25, 2026
8f9365b
Require JDK 17+ for consistency with the rest of Spine SDK
alexander-yevsyukov May 25, 2026
f727649
Bump Gradle -> `9.5.1`
alexander-yevsyukov May 25, 2026
9c2a276
Remove the unused task `buildAll`
alexander-yevsyukov May 25, 2026
790dc91
Remove the temporary script
alexander-yevsyukov May 25, 2026
c05a1c5
Improve lookup for Hugo site settings
alexander-yevsyukov May 25, 2026
064dbc2
docs: align Go prerequisite with go.mod
Copilot May 25, 2026
c2860d4
Update Java level in IDEA settings
alexander-yevsyukov May 25, 2026
b746e3c
Merge remote-tracking branch 'origin/add-config' into add-config
alexander-yevsyukov May 25, 2026
a39b06f
Fix spelling mistake
alexander-yevsyukov May 25, 2026
b0e905f
Fix spelling mistake in README.md template
alexander-yevsyukov May 25, 2026
80028fe
Add DOMPurify for XSS protection in Markdown rendering
alexander-yevsyukov May 25, 2026
4699322
Correct settings items indexing
alexander-yevsyukov May 25, 2026
9101337
Improve repo link
alexander-yevsyukov May 25, 2026
1bb18b9
Pin DOMPurify to exact version `3.4.5`
alexander-yevsyukov May 25, 2026
bad19fd
Fix week-based year date format
alexander-yevsyukov May 25, 2026
9ef56e6
Remove `project-overview.md`
alexander-yevsyukov May 25, 2026
365765e
Use newer Node for publishing
alexander-yevsyukov May 25, 2026
730def1
Fix JDK name in settings
alexander-yevsyukov May 25, 2026
77c389e
Check presence of `jq` utility
alexander-yevsyukov May 25, 2026
bf2cde2
Use `data-` attribute prefixes
alexander-yevsyukov May 25, 2026
54634d7
Suppress warnings
alexander-yevsyukov May 25, 2026
231a083
Match skill descriptions with impl. details
alexander-yevsyukov May 25, 2026
2f14ca3
Fix the comment from Copilot
alexander-yevsyukov May 25, 2026
7ecbe33
Load script from cdn.jsdelivr.net
alexander-yevsyukov May 25, 2026
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
23 changes: 23 additions & 0 deletions .agents/_TOC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Table of Contents

1. [Quick Reference Card](quick-reference-card.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)
6. [Running builds](running-builds.md)
7. [Version policy](version-policy.md)
8. [Project structure expectations](project-structure-expectations.md)
9. [Testing](testing.md)
10. [Safety rules](safety-rules.md)
11. [Advanced safety rules](advanced-safety-rules.md)
12. [Refactoring guidelines](refactoring-guidelines.md)
13. [Common tasks](common-tasks.md)
14. [Team memory](memory/MEMORY.md)
15. [Task plans](tasks/README.md)
16. [Java to Kotlin conversion](skills/java-to-kotlin/SKILL.md)
17. [Dependency update](skills/dependency-update/SKILL.md)
18. [Documentation review](skills/review-docs/SKILL.md)
19. [Pre-PR checklist](skills/pre-pr/SKILL.md)
20. [Kotlin code review](skills/kotlin-review/SKILL.md)
21. [Dependency audit](skills/dependency-audit/SKILL.md)
6 changes: 6 additions & 0 deletions .agents/advanced-safety-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 🚨 Advanced safety rules

- Do **not** auto-update external dependencies without explicit request.
- Do **not** inject analytics or telemetry code.
- Flag any usage of unsafe constructs (e.g., reflection, I/O on the main thread).
- Avoid generating blocking calls inside coroutines.
39 changes: 39 additions & 0 deletions .agents/coding-guidelines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 🧾 Coding guidelines

## Core principles

- Adhere to [Spine Event Engine Documentation][spine-docs] for coding style.
- Generate code that compiles cleanly and passes static analysis.
- Respect existing architecture, naming conventions, and project structure.
- Write clear, incremental commits with descriptive messages.
- Include automated tests for any code change that alters functionality.

## Kotlin best practices

### ✅ Prefer
- **Kotlin idioms** over Java-style approaches:
- Extension functions
- `when` expressions
- Smart casts
- Data classes and sealed classes
- Immutable data structures
- **Simple nouns** over composite nouns (`user` > `userAccount`)
- **Generic parameters** over explicit variable types (`val list = mutableList<Dependency>()`)
- **Java interop annotations** only when needed (`@file:JvmName`, `@JvmStatic`)
- **Kotlin DSL** for Gradle files

### ❌ Avoid
- Mutable data structures
- Java-style verbosity (builders with setters)
- Redundant null checks (`?.let` misuse)
- Using `!!` unless clearly justified
- Type names in variable names (`userObject`, `itemList`)
- String duplication (use constants in companion objects)
- Mixing Groovy and Kotlin DSLs in build logic
- Reflection unless specifically requested

## Text formatting
- ✅ Replace double empty lines with a single empty line in the code.
- ✅ Remove trailing space characters in the code.

[spine-docs]: https://github.com/SpineEventEngine/documentation/wiki
6 changes: 6 additions & 0 deletions .agents/common-tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 📋 Common tasks

- **Adding a new dependency**: Update relevant files in `buildSrc` directory.
- **Creating a new module**: Follow existing module structure patterns.
- **Documentation**: Use KDoc style for public and internal APIs.
- **Testing**: Create comprehensive tests using Kotest assertions.
14 changes: 14 additions & 0 deletions .agents/documentation-guidelines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Documentation & comments

## Commenting guidelines
- Avoid inline comments in production code unless necessary.
- Inline comments are helpful in tests.
- When using TODO comments, follow the format on the [dedicated page][todo-comments].
- File and directory names should be formatted as code.

## Avoid widows, runts, orphans, or rivers

Agents should **AVOID** text flow patters illustrated
on [this diagram](widow-runt-orphan.jpg).

[todo-comments]: https://github.com/SpineEventEngine/documentation/wiki/TODO-comments
20 changes: 20 additions & 0 deletions .agents/documentation-tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 📄 Documentation tasks

1. Ensure all public and internal APIs have KDoc examples.
2. Add in-line code blocks for clarity in tests.
3. Convert inline API comments in Java to KDoc in Kotlin:
```java
// Literal string to be inlined whenever a placeholder references a non-existent argument.
private final String missingArgumentMessage = "[MISSING ARGUMENT]";
```
transforms to:
```kotlin
/**
* Literal string to be inlined whenever a placeholder references a non-existent argument.
*/
private val missingArgumentMessage = "[MISSING ARGUMENT]"
```

4. Javadoc -> KDoc conversion tasks:
- Remove `<p>` tags in the line with text: `"<p>This"` -> `"This"`.
- Replace `<p>` with empty line if the tag is the only text in the line.
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
17 changes: 17 additions & 0 deletions .agents/memory/MEMORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Team memory index

One line per memory. Scan at the start of every session.
See [README.md](README.md) for the format and routing rules.

## Feedback (validated patterns & corrections)

- [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)

- [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.
89 changes: 89 additions & 0 deletions .agents/memory/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Team memory — `.agents/memory/`

Validated patterns, durable project context, and pointers to external
systems. Checked into git so the whole team — and any agent working in
this repo — benefits from accumulated knowledge.

This complements Claude Code's built-in per-developer auto-memory:
team-shareable knowledge lives here; personal preferences and ephemeral
state live in the auto-memory.

## Layout

.agents/memory/
├── MEMORY.md # Index — scan at start of every session
├── README.md # This file — read when adding/updating memories
├── feedback/ # Validated patterns & corrections
├── project/ # Durable project context & rationale
└── reference/ # External systems & resources

One file per memory. Filename = the memory's kebab-case slug.

## File format

---
name: tests-no-db-mocks
description: One-line summary — used to surface relevance, so be specific.
metadata:
type: feedback # feedback | project | reference
since: 2026-05-19 # date added (ISO)
---

<one-paragraph rule or fact>

**Why:** <reason — incident, constraint, team convention>

**How to apply:** <when this kicks in; what to do or avoid>

Related: [[other-memory-slug]]

`Why:` and `How to apply:` are required for `feedback` and `project`
memories — they let future readers judge edge cases. `reference`
memories may be shorter (link + one-line purpose).

Link related memories with `[[slug]]` (the target file's `name:`).

## Routing — repo vs. auto-memory

| Kind of fact | Goes to |
|---|---|
| Personal preference, role, style | auto-memory (`user`) |
| Personal habit feedback | auto-memory (`feedback`) |
| Team coding/test/PR rule | **`feedback/`** |
| Durable project rationale | **`project/`** |
| Ephemeral project state (freezes, OOO, deadlines) | auto-memory (`project`) — would rot in git |
| Team-shared external resource | **`reference/`** |
| Personal external resource | auto-memory (`reference`) |

**Litmus test:** *would a teammate joining the project next month benefit
from knowing this?* If no, it belongs in auto-memory.

## Write protocol

1. Write the file **uncommitted** in the working tree.
2. **Surface the change** in the same turn so the human can review.
3. **Do not auto-commit** memory edits as part of an unrelated PR — memory
changes should be reviewable on their own.
4. **Correct in place** when an existing memory turns out wrong; `git blame`
carries the history.
5. **Propose deletion explicitly** when a memory has gone stale, rather
than silently editing it out.

## Updating the index

After adding or removing a memory file, update `MEMORY.md`. One line under
the matching section:

- [slug](category/slug.md) — description from frontmatter

Keep the index short — long descriptions belong in the file body.

## Anti-patterns — do not store

- Anything derivable from the code (module structure, paths, conventions
visible in source). Use `grep` / `Read`.
- Recent-activity summaries or PR lists — `git log` is authoritative.
- Fix recipes for specific bugs — the commit message belongs in the commit.
- Anything already documented in `.agents/` reference docs — keep one
source of truth.
- Personal preferences (see routing).
Empty file.
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.
Empty file added .agents/memory/project/.gitkeep
Empty file.
Empty file.
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]]
Loading
Loading