mirror of
https://github.com/Donchitos/Claude-Code-Game-Studios.git
synced 2026-10-16 01:37:05 +00:00
Release 1.1.0 — one config file, and a process weight you choose
`project.yaml` at the repo root is now the single source of truth for a project's configuration, replacing `production/stage.txt`, `production/review-mode.txt` and `.claude/docs/technical-preferences.md` (all three still read as a fallback; nothing is force-deleted). **`modes.rigor` — one question instead of six.** `minimal`, `standard` or `full` fronts six knobs: `modes.workflow`, `docs.density`, `qa.level`, `modes.story_granularity`, `modes.review_mode` and `team.size`. It defaults to `minimal`, which is a change from 1.0's behaviour: the heavier tier was measured costing several times more to reach working code without producing a better result, and returning nothing when a fresh developer inherited the project. Pin `modes.rigor: standard` to keep 1.0's process level. Also in this release: - `/settings` to view or change any setting, and `project.local.yaml` for per-developer preferences that should not be committed. - `system_overrides` to hold one system to a higher standard than the rest of the project, and `testing.strict` to set per test type whether missing evidence blocks a story or warns. - A story that changes anything the player sees is not closed until the game has been launched, observed, and a screenshot retained in `production/qa/evidence/`. A parse check is not a run. This holds at every rigor level, including `minimal`, where automated tests are waived but the look is not. - The code root is engine-specific and enforced as such: Godot `src/`, Unity `Assets/`, Unreal `Source/<Module>/`. Two of the three will not build a project laid out any other way. - Migration tooling for existing projects: `.claude/scripts/migrate-v1-config.sh` converts a 1.0 layout, non-destructively by default, with a report to review before `--finalize` deletes anything. - Ask-before-write holds regardless of personal automation settings. Upgrading from 1.0 or earlier: see UPGRADING.md. Full list of changes: CHANGELOG.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016xvzG3i7pWQg4LjyDwWMXd
This commit is contained in:
co-authored by
Claude Opus 5
parent
984023ddac
commit
d05699707f
@@ -0,0 +1,55 @@
|
||||
---
|
||||
paths:
|
||||
- ".claude/agent-memory/**"
|
||||
---
|
||||
|
||||
# Agent Memory Rules
|
||||
|
||||
**Agent memory is the one place an agent may write without asking — and the only
|
||||
one.** `.claude/agent-memory/` is gitignored, per-agent, and never ships. That
|
||||
exemption exists because the memory is the agent's own working notes about how to
|
||||
do its job, not a project artifact.
|
||||
|
||||
It does **not** extend anywhere else. The Collaboration Protocol still governs
|
||||
every file under `src/`, `design/`, `docs/`, `production/` and `assets/`: ask
|
||||
first, naming the path. Writing a memory is never a substitute for asking, and a
|
||||
memory must never be used to record something the user declined to have written.
|
||||
|
||||
## Never record a temporary absence as a durable fact
|
||||
|
||||
This is the failure this file exists to prevent, and this repo is unusually
|
||||
exposed to it.
|
||||
|
||||
**CCGS ships as a template the user clones *as their game*.** So on day one every
|
||||
agent observes the same things — no `src/`, no GDDs, no engine configured, no
|
||||
`tests/performance/` — and every one of those observations is **guaranteed to
|
||||
stop being true**. A memory reading *"this repo is the framework, not a game;
|
||||
perf requests have no target"* is accurate when written and actively harmful two
|
||||
weeks later, when it tells a future run to return BLOCKED on a project that now
|
||||
has a build. The agent will not re-derive it; that is what memory is for.
|
||||
|
||||
So:
|
||||
|
||||
- **Prefer recording a method over a state.** "Confirm an engine project and a
|
||||
captured profile exist before profiling; return BLOCKED naming what is missing
|
||||
rather than estimating" is durable. "There is no game here" is a timestamp.
|
||||
- **If you must record a state, state what invalidates it**, on the same line:
|
||||
`INVALIDATED WHEN: project.yaml declares an engine, or src/ contains game code.`
|
||||
A reader with no other context must be able to tell whether the note still
|
||||
holds.
|
||||
- **Never record absence of a game, of assets, of tests or of config as a
|
||||
settled property of the project.** Those are the states CCGS exists to move a
|
||||
user out of.
|
||||
|
||||
## Disclose the write
|
||||
|
||||
Say in your response that you recorded a memory and where. An unmentioned write
|
||||
is indistinguishable from no write, and the user cannot correct a note they do
|
||||
not know exists — the same reason a skipped check has to announce itself
|
||||
(`.claude/rules/skill-authoring.md`, obligation 3).
|
||||
|
||||
## Verify before you trust
|
||||
|
||||
A recalled memory reflects what was true when it was written. If it names a file,
|
||||
a path, a setting or a count, **check that it still holds before acting on it**.
|
||||
Memory is a starting point for investigation, never evidence.
|
||||
@@ -9,7 +9,19 @@ paths:
|
||||
- File naming: lowercase with underscores only, following `[system]_[name].json` pattern
|
||||
- Every data file must have a documented schema (either JSON Schema or documented in the corresponding design doc)
|
||||
- Numeric values must include comments or companion docs explaining what the numbers mean
|
||||
- Use consistent key naming: camelCase for keys within JSON files
|
||||
- Use consistent key naming: **`snake_case` for keys within JSON files**, matching
|
||||
the `[system]_[name].json` file convention one line above and the engine idiom
|
||||
every other standard in this repo uses.
|
||||
|
||||
> **On Unity and Unreal this costs you a mapping layer — budget for it rather
|
||||
> than changing the keys.** `JsonUtility` binds by *exact field name*, and C#
|
||||
> fields are `camelCase` per `naming.variables`, so a snake_case file cannot bind
|
||||
> directly to the type that consumes it. Use a private nested DTO whose fields
|
||||
> are the wire format and which maps once into your real type, or take a
|
||||
> dependency that supports a naming policy (Newtonsoft `SnakeCaseNamingStrategy`,
|
||||
> `System.Text.Json` `JsonNamingPolicy`). Do **not** switch the file to camelCase
|
||||
> to avoid the DTO: keys are the cross-engine contract. Write the DTO and
|
||||
> document it as a wire-format boundary — that is the intended shape.
|
||||
- No orphaned data entries — every entry must be referenced by code or another data file
|
||||
- Version data files when making breaking schema changes
|
||||
- Include sensible defaults for all optional fields
|
||||
@@ -21,16 +33,16 @@ paths:
|
||||
```json
|
||||
{
|
||||
"goblin": {
|
||||
"baseHealth": 50,
|
||||
"baseDamage": 8,
|
||||
"moveSpeed": 3.5,
|
||||
"lootTable": "loot_goblin_common"
|
||||
"base_health": 50,
|
||||
"base_damage": 8,
|
||||
"move_speed": 3.5,
|
||||
"loot_table": "loot_goblin_common"
|
||||
},
|
||||
"goblin_chief": {
|
||||
"baseHealth": 150,
|
||||
"baseDamage": 20,
|
||||
"moveSpeed": 2.8,
|
||||
"lootTable": "loot_goblin_rare"
|
||||
"base_health": 150,
|
||||
"base_damage": 20,
|
||||
"move_speed": 2.8,
|
||||
"loot_table": "loot_goblin_rare"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,7 +5,10 @@ paths:
|
||||
|
||||
# Design Document Rules
|
||||
|
||||
- Every design document MUST contain these 8 sections: Overview, Player Fantasy, Detailed Rules, Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria
|
||||
- The 8 GDD sections are: Overview, Player Fantasy, Detailed Rules, Formulas, Edge Cases, Dependencies, Tuning Knobs, Acceptance Criteria
|
||||
- **How many are required depends on `modes.workflow`** — all 8 at `full`, 5 (+ Formulas when the system **defines numeric rules**: rates, curves, thresholds, costs, damage, drop weights — anything a balance pass would tune) at `standard`, none at `minimal` (the design record there is `design/game-brief.md`). Resolve the tier before flagging a section as missing; see `.claude/docs/workflow-modes.md`
|
||||
- **The Formulas test is what the system defines, not what it is called.** A system's `Category` in `systems-index.md` is a hint — `Gameplay`, `Economy` and `Progression` almost always qualify — never the test. Do not gate Formulas on a category token: the categories `/map-systems` writes (`Core · Gameplay · Progression · Economy · Persistence · UI · Audio · Narrative · Meta`) do not include `combat` or `AI`, which are example systems *within* `Gameplay`. Every site stating this rule must state the same test.
|
||||
- **Section-name alias**: The GDD template and `/design-system` author this section as `## Detailed Design`; the design standard calls it **Detailed Rules**. These are the SAME required section — accept either heading and never rewrite one into the other.
|
||||
- Formulas must include variable definitions, expected value ranges, and example calculations
|
||||
- Edge cases must explicitly state what happens, not just "handle gracefully"
|
||||
- Dependencies must be bidirectional — if system A depends on B, B's doc must mention A
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
paths:
|
||||
- ".claude/skills/**"
|
||||
- ".claude/agents/**"
|
||||
---
|
||||
|
||||
# Skill and Gate Authoring
|
||||
|
||||
**A check that cannot report that it did not run is not a check.**
|
||||
|
||||
The same shape recurs across unrelated subsystems, so treat it as the default
|
||||
risk in any check you write, not as an unusual mistake.
|
||||
|
||||
The failure is always the same trade: a step that could not run produces output
|
||||
indistinguishable from a step that ran and found nothing. Nobody reading the
|
||||
output can tell which happened, and the permissive reading is the one that gets
|
||||
believed, because it is the one that lets work proceed.
|
||||
|
||||
## The five obligations
|
||||
|
||||
### 1. Every gating verdict needs a "could not assess" value
|
||||
|
||||
If a skill emits a verdict something else depends on, its vocabulary must include
|
||||
one — `NOT ASSESSED`, or the local equivalent — and the report must say *which*
|
||||
of the reasons applied. A vocabulary of three confident verdicts forces every
|
||||
unknown into a claim.
|
||||
|
||||
**Rank it deliberately.** It must outrank the pass value: a run that could not
|
||||
assess part of its scope has not established that the scope is good. It must
|
||||
**not** outrank the failure values: a known problem is more actionable than an
|
||||
unknown, and demoting a real failure behind an access problem buries it.
|
||||
|
||||
**`NOT ASSESSED` is not a gentler failure verdict.** "I looked and found nothing"
|
||||
and "I could not look" have different fixes — one needs work done, the other
|
||||
needs access granted or an input classified. Collapsing them sends the reader to
|
||||
the wrong fix.
|
||||
|
||||
### 2. An absent value may not default to the permissive one
|
||||
|
||||
Especially when **nothing in the framework writes that key**. Before defaulting,
|
||||
check who sets it: a key with a reader and no writer takes its default branch on
|
||||
every project that ever runs, so that branch is not an edge case — it is the
|
||||
behaviour.
|
||||
|
||||
Over-running a check costs minutes. Under-running one ships the category unrun.
|
||||
|
||||
### 3. A skipped step announces itself
|
||||
|
||||
In the output, not only in the source. If a phase, category, or agent did not run
|
||||
— wrong engine, missing config, unavailable input, a `team.size` that collapses
|
||||
the pipeline — the artifact must say so by name. A silent skip and a successful
|
||||
one are the same artifact.
|
||||
|
||||
A rule enforced in the body and never surfaced in the output is, to the reader,
|
||||
identical to no rule at all.
|
||||
|
||||
### 4. Never assert what you cannot source — and wire the gap to the verdict
|
||||
|
||||
Where this repo pins external facts (`docs/engine-reference/**`), do not fill a
|
||||
gap from training data. Write the gap down instead: `NOT SOURCEABLE — <what> is
|
||||
not covered by <path>`.
|
||||
|
||||
**Flagging alone is not enough.** A named gap that does not reach the verdict is
|
||||
just a comment. Wire it: a category with no sourced inputs must force obligation
|
||||
1's value, so the gap makes the pass unreachable rather than sitting beside it.
|
||||
|
||||
A confidently wrong pattern list is worse than an absent one — it produces a scan
|
||||
that looks thorough, finds nothing, and reads as a pass.
|
||||
|
||||
### 5. Gates derive their covered set; they do not enumerate it
|
||||
|
||||
An allowlist pins what was known when it was written and is silent about
|
||||
everything added since. Derive the set from what the repo actually contains, so a
|
||||
new skill or agent cannot ship outside coverage by simply not being on a list.
|
||||
|
||||
**If the category is not mechanically crisp, say so in the gate and keep the
|
||||
list.** A gate that fires on forty files does not get fixed, it gets muted — and
|
||||
a muted gate is worse than a narrow one, because it reads as coverage. When you
|
||||
keep a list, record *why* derivation failed and state the obligation to extend it.
|
||||
|
||||
Two further gate rules earned the hard way:
|
||||
|
||||
- **Assert something that cannot be true by accident.** A check for the word
|
||||
"unity" was satisfied by a file path, and case-insensitively by "community".
|
||||
Assert a distinctive token instead.
|
||||
- **A gate you have not watched fail is not a gate.** Break the thing it guards,
|
||||
confirm it fails, restore. One mutation per tool invocation — a batch that
|
||||
times out leaves the repo holding a broken file, and `trap … EXIT` does not
|
||||
survive `SIGTERM`.
|
||||
|
||||
## Evidence
|
||||
|
||||
Every row below is a real instance this rule was written to prevent.
|
||||
|
||||
| Where | What was indistinguishable from success |
|
||||
|---|---|
|
||||
| `team-*` engine step | Specialist skipped when no engine configured — output identical to a run that consulted one |
|
||||
| `team-ui` accessibility gate | Passed vacuously; its criterion file did not exist |
|
||||
| `yaml-helper` | Locked key in `project.local.yaml` dropped in silence; user saw the default they were overriding |
|
||||
| all nine `team-*` | Pipeline printed six agents and ran one, with no statement of the difference |
|
||||
| `/security-audit` | Godot-only greps returned zero hits on Unity/Unreal, and zero hits read as clean |
|
||||
| `unity/VERSION.md` | "Post-cutoff" table listed pre-cutoff versions, inverting the signal it exists to send |
|
||||
| `/security-audit` | `platform.multiplayer` had a reader and no writer; the network category never ran, on any project |
|
||||
| `test-evidence-review` | No verdict for "could not check", so an unverifiable story got a verdict saying it was verified |
|
||||
| the gate meant to catch all of this | Was a hand-written list, and read green over the gap |
|
||||
|
||||
## The test to apply
|
||||
|
||||
Before shipping a skill or gate, ask: **if this step silently did not run, what
|
||||
would the output look like?**
|
||||
|
||||
If the answer is "the same", it is not finished.
|
||||
@@ -12,7 +12,18 @@ paths:
|
||||
- Performance tests must specify acceptable thresholds and fail if exceeded
|
||||
- Test data must be defined in the test or in dedicated fixtures, never shared mutable state
|
||||
- Mock external dependencies — tests should be fast and deterministic
|
||||
- Every bug fix must have a regression test that would have caught the original bug
|
||||
- Every bug fix must have a regression test that would have caught the original bug —
|
||||
and **you must watch it fail before you trust it.** Run the new test against the
|
||||
unfixed code, confirm it fails, then apply the fix and confirm it passes. A
|
||||
regression test that has only ever been seen passing is not known to test anything.
|
||||
|
||||
> This is `.claude/rules/skill-authoring.md`'s "a gate you have not watched fail
|
||||
> is not a gate", applied to tests. It is written out here because stating the
|
||||
> *goal* is not enough. A regression test for an iteration-order defect can use
|
||||
> a fixture where no cell takes part in two transfers per tick — it then passes
|
||||
> against the very bug it was written for, and looks authoritative doing it. The
|
||||
> fixture, not the assertion, is what makes it useless, and only running it
|
||||
> against the unfixed code exposes that.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
Reference in New Issue
Block a user