The per-commit clerk had three flaws, exposed by a 20-commit push where 6 of 7
rejections were false (incl. a CHANGELOG-only commit):
1. No-verdict / max-turns / timeout defaulted to REJECTED — an unfinished review
read as 'hard contradiction found'. Now a third outcome, INCOMPLETE, which is
non-blocking (the push proceeds with a warning); only a real REJECTED blocks.
2. Turn/time budget too tight (6 turns / 150s) for decision-heavy commits. Raised
defaults to 15 turns / 300s, and the prompt now biases to APPROVED when no
concrete contradiction is found ('unsure' means APPROVED, never REJECTED).
3. The skip valve matched its own feature commit because it scanned for the token
anywhere in the message. Moved to a trailer-line match so prose/subject mentions
no longer trip it.
Pre-push hook updated to treat INCOMPLETE as a non-blocking warning. The git-commit
skill documents the trailer form.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A commit whose message contains the token [clerk-skip] is auto-approved by
the pre-push clerk without spawning an agent. Intended for bulk content/data
commits — e.g. shipping thousands of generated planetary description files —
where D-record review is moot and would only burn agents on noise.
Documented in the /git-commit skill with the caveat: never use it on commits
that touch decisions/, code, or ticket-bearing work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The tmux teammate-mode investigation is resolved (works on 2.1.148; the
'broken regression' was a teammateMode: in-process config issue). Per the
file's own cleanup note, delete it now that the test passes.
Update the two references:
- decisions/questions-process.md: replace the stale 'partially broken'
pointer with the resolved status.
- whats-next/SKILL.md: the 'custom subagent_types lose SendMessage' caveat is
fixed (all agents now carry SendMessage + Task tools), so reword and drop
the dead team-test.md link.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two agent-team tooling changes:
- teammateMode: in-process -> auto. Teammates now spawn in tmux split panes
when the lead runs inside tmux, with graceful in-process fallback.
- New PreToolUse hook git-centralize-guard.sh blocks .git-mutating commands
(add, commit, merge, push, pull, rebase, reset, checkout, stash,
cherry-pick, rm, mv) for teammates, keeping version control centralized to
the lead. Detection keys on the agent_type field, which a teammate's hook
input carries and the lead's does not. Read-only git is allowed.
Documented in .claude/rules/git-safety.md. Hooks load at lead startup, so a
restart is required for the hook to reach teammates.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Custom subagent types used as agent-team teammates in tmux pane mode only
receive their definition's restricted tools list — the coordination tools
are not injected (confirmed on Claude Code 2.1.148). Without SendMessage a
teammate can't message the lead and can't return a shutdown_response, so it
orphans its pane.
Add SendMessage, TaskList, TaskUpdate, and TaskGet to all 21 agents so they
work as full teammates. TaskCreate is intentionally omitted: task creation
stays centralized with the team lead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a mandatory step between assessing changes and grouping commits:
surface any modified/untracked files that weren't touched in the current
session and ask the user whether to include them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint-based workflow (38 sprints) replaced by kanban + milestones.
Milestones are many-to-many with tickets and can block each other.
New: /whats-next skill (dependency-driven batch selection with Si
refinement review), /pr-process skill (renamed from pr-push, adds
review comment pickup), clerk agent + pre-push hook for D-record
consistency checks.
Deleted: sprint CLI, sprint-start/sprint-plan/sprint-status skills,
team-scoped file restrictions. Si rewritten as refinement manager.
All 19 agent briefings updated from stale PROJECT_STATE.md reference
to live ticket milestone queries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add gemma_naming.py and naming_core.py to generate_atlas source
tracking in check-systems-db-stamp. Mirror in pr-push watch list.
Prevents naming helper changes from bypassing stale-stamp detection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
asset-pipeline.md (2 locations) and systems-schema.sql still pointed
at import_economics.py as the SCHEMA_VERSION home after the extraction
to a shared module.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. decisions_sync.py: fix refs_created inflation (check rowcount),
remove dead IntegrityError except block
2. Extract SCHEMA_VERSION to shared tooling/schema_version.py —
both generators import from single source of truth
3. generate_atlas.py: narrow bare except to OperationalError +
"duplicate column" check
4. check-systems-db-stamp: add cross-generator schema_version
agreement assertion (defense-in-depth)
5. decision wrapper: add show + orphan-tickets to usage text
6. Add schema_version.py to all three source watch lists
(GENERATOR_SOURCES, IMPORT_ECONOMICS_SOURCES, generate_atlas
_write_stamp) — prevents silent staleness on version bump
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace SHA-1 hash in meta.schema_version with an orderable semver
string ("1.0.0"). SHA preserved in new schema_sha column for tamper
detection. Enables savegame migration lineage in Phase 5+ — saves can
record their schema version and determine which migrations to apply.
Updated both generators, check-systems-db-stamp validation (rejects
old SHA-hex values), schema DDL, and asset-pipeline docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generation pipeline focus — map all layers from planetary heightmaps to
walkable tile environments, build bare-minimum free camera viewer, close
Sprint 37 test/infra debt. Character and apartment work formally parked
behind the full generation cascade.
13 tickets across 5 teams (planning: 1, server: 4, client: 5, copy: 1, ci: 2).
Added Write(docs/sprints/*) and Bash(mkdir) permissions for sprint planning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sprint 37 PR #138 review produced 6 false-positive findings because
the reviewer defaulted to Read/Grep on the main repo path instead of
the sprint-37/copy branch worktree. Every finding was a verbatim match
against main's state but irrelevant to the branch — the branch had
already cleaned the residue being flagged as "still present." False
negatives are the same drift running the other direction: bugs
introduced on the branch never get seen because the reviewer never
reads the branch.
Fix: resolve the team worktree path before spawning reviewers
($(dirname <repo>)/.sprint/sprint-N/<team>/) and pass it into the
reviewer prompt with non-negotiable language. The worktree IS the
branch; Read/Grep on paths rooted there cannot resolve to main.
Fallback (no worktree — e.g. non-sprint branch or post-teardown):
git show origin/<branch>:<path>. Explicitly flagged in the prompt
so the reviewer knows Read/Grep on any local path is wrong.
Addresses all blocking + minor items from PR #136 review.
Architectural change (T2/H3 — the review's main complaint):
generate_brands was previously a separate Rust binary that produced a TOML
artifact, with its stamp written "on behalf" by import_economics.py at the
end of its own run. Reviewers flagged the invisible coupling: two sources
of truth in a system designed to have one, and no way to tell from the
stamp that one "generator" was really a subroutine of the other.
import_economics now invokes tooling/generate-brands as the first step of
its main() flow, before opening its own DB connection. The TOML artefact
is still produced and still committed (useful for diff-review of brand
changes), but there's now one pipeline owner. The meta table carries two
rows (import_economics, generate_atlas) not three; the Rust binary's
source SHA folds into import_economics' stamp via IMPORT_ECONOMICS_SOURCES.
A MIGRATION_SQL DELETE cleans up pre-merge DBs that still have the
orphan generate_brands row.
Other review items addressed in-line:
H1 generate_atlas._write_stamp no longer commits — transaction ownership
stays with the caller (matches import_economics pattern). Stamp +
atlas data now commit atomically; a failed stamp rolls back the
atlas data rather than leaving a stamp-missing-data intermediate.
H2 _file_sha1 (in both import_economics, generate_atlas,
check-systems-db-stamp) raises FileNotFoundError on missing sources
instead of silently contributing an empty-bytes hash. A ghost-SHA
convergence could otherwise produce vacuous "fresh" passes.
H4 pre-push no-meta-table warning rephrased — was "run after next
regeneration", now "run now if this DB was generated by you".
T1 asset-pipeline.md determinism claim softened: the stamp is
deterministic (same source → same recorded SHA), the DB binary is
not (generated_at + SQLite rowids/freelist churn).
T3 asset-pipeline.md gains a "migration escape hatch" section naming
MIGRATION_SQL in import_economics.py as the only sanctioned path
for direct writes, and forbidding hand-run sqlite-exec / one-off
patch scripts / SQLite-GUI edits.
T4 Makefile regen-db now runs as a single shell with `set -e`. A
failure in one generator halts the pipeline immediately, preventing
the "stale data, fresh stamp" state where a later step stamped a
DB whose earlier step had failed. import_economics' exit code 2
(coverage gate warning) remains explicitly tolerated.
T5 pre-push stamp check now runs on a branch's first push too —
compares against origin/main instead of origin/$BRANCH, closing
the gap where a new branch could ship a stale DB via the first push.
T6 check-systems-db-stamp fails closed on unknown generator_names in
meta — a future branch adding a new generator without registering
it in GENERATOR_SOURCES will now be rejected, not silently skipped.
T7 /pr-push watch list gains a mutual cross-reference comment with
GENERATOR_SOURCES in check-systems-db-stamp, plus the missing
names.rs source file, so the two lists cannot silently drift.
Follow-up tickets created:
#887 T8 decisions-orphan-tickets CLI — surfaces tickets whose
decision_ref points at a non-existent D-record.
#888 T9 meta.schema_version monotonic semver — for savegame migration
lineage in Phase 5+ (SHA comparison can't be ordered).
Verified:
make regen-db end-to-end — OK
make check-systems-db — OK, 2 generator(s) up to date
STALE detection — OK, verified by touching generate_atlas.py
/pr-push watch list — OK, flags this branch's changed sources
decision show D-159 — OK, structured output with tickets + refs
Refs: #855#856#857#858#859 PR #136
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 37 observed Opus 4.7 teammates in team mode ignoring scope
rules ("don't modify files outside your team"), leaving tasks
half-done, and failing to report back via SendMessage. Closest public
issues are anthropics/claude-code#47598 (4.6 subagent delegation
regression) and claude-agent-sdk-python#577 (SendMessage delivery in
team mode). No 4.7-specific team-mode issue published yet but symptoms
are real.
Fix: every Task spawn with a team_name argument now passes
model: "sonnet". The team lead (the session running the skill) stays
on whatever model the user selected — typically Opus.
Inline Agent spawns without team_name (one-shot reviewers in
/pr-review, research subagents, general-purpose one-offs) are
exempt — they keep their default model. The pin targets long-running
coordination specifically, not every Agent call.
Affected skills:
- sprint-start: step 8d Task template adds model: "sonnet" and
documents the rule with the 4.7 regression context
- workshop-start: step 5 spawn list adds the model pin with a
one-line reason
Adds `.claude/rules/asset-pipeline.md` describing the full pipeline —
generators, meta stamp, pre-push hook, how to make DB/schema changes,
and why direct systems.db edits are forbidden. CLAUDE.md and DEVOPS.md
point at the rules file; sprint-start template now reminds teammates
to read it before touching DB sources.
CLAUDE.md also gains the missing `decision show` row in the CLI tool
table (companion to #723's `decision show` subcommand).
Refs: #859#723
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new step 4a that detects generator-source or economy-data changes
vs origin/main and runs `make regen-db` before the push, staging the
updated systems.db. Pairs with the pre-push hook (#857) — instead of
rejecting a stale DB, /pr-push proactively freshens it.
Refs: #858
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The worktree cleanup step was documented as "safe to skip if the
sprint didn't use ephemeral worktrees" — which invited a pre-check.
Sprint 36 close did that pre-check from inside the repo root, where
.sprint/ doesn't exist, concluded no worktrees, and skipped teardown.
Three stale worktrees persisted until Sprint 37 planning surfaced them.
Fix: always run the script (idempotent, prints a graceful message when
empty). Document that .sprint/ is a sibling of the repo root, not a
child, so future sessions don't repeat the same ls-based pre-check.
Add a post-run verification step.
- pr-review: require manual smoke test for merge-path PRs (pre-game flow,
scene transitions, save/load, connection handshake). Unchecked
author-side smoke boxes downgrade verdict from APPROVED to
REQUEST_CHANGES. Triggered by #872 — New Game hangs on 'connecting'
landed through PR #134 with the exact smoke box unchecked.
- pr-push: wipe Godot script class cache before the runtime smoke check
so cold-start parse-order bugs surface pre-push instead of failing
the next fresh-clone parse. Sprint 36 hit this post-merge — MetaScreen
base class not found because the cache was warm on developer machines
but cold in CI / post-merge. Cold-cache check stays in the skill (not
the pre-push hook) to keep iteration fast.
Two Sprint 36 lessons folded into the pr-push skill's pre-push
workflow.
1a (new, mandatory). Orphan Godot process check. `ps -eo pid,etimes,cmd
| awk` filter for `godot.*gdunit4-run` processes running longer than
5 minutes. Ask the user before killing. Blocks Sprint 36's failure
mode where stale background test-runner invocations (from an earlier
hung run) silently wedged fresh test runs by stealing CPU — an hour
of verification time lost to exactly this.
1c (widened). Headless parse + scanner check. The old grep was
`grep -i "SCRIPT ERROR"`, which missed Godot's resource scanner
category errors like "Export type can only be built-in, a resource,
a node, or an enum" — those surface as plain `ERROR` lines, not
prefixed `SCRIPT ERROR`. Widened to
`grep -iE "^(SCRIPT )?ERROR|Parse Error|Export type"` and filtered
against the known pre-existing autoload class_name parse-order
noise (Messagepack, LocalBridge, ServerProcess, Constants — per
CLAUDE.md's documented trap). Commit 84105916 shipped an
`@export var descriptor: CharacterVisualDescriptor` issue that the
narrower grep missed; Tyre caught it five commits later.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both lint tools are used during pr-review pre-flight checks. Adding them
alongside the existing cargo check / test / build entries avoids
permission prompts during the review cycle.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md: add "Pair session" as formal work mode alongside sprint mode
- Scrap NPC ambient systems (R-012): D-078 marked superseded, content
pattern note scrapped, overheard conversation system will be rebuilt
from scratch after a walkable environment exists
- Agent profiles: remove NPC-drift references from Paula, Dudley, Miri;
add cascade discipline to Miri's role
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Qdrant index (commonwealth collection, 475 points) was stale —
pointing at old worktree paths from previous sprints with no
maintenance. Grep covers all current search needs.
Removed: qdrant_connector.py, wrapper scripts (qdrant-search,
qdrant-index, qdrant-health, qdrant-count), /docs-search skill,
Qdrant/Ollama config entries, and all active references in agents,
rules, briefings, DEVOPS, CLAUDE.md, and TEAM.md. The commonwealth
collection was dropped from tower-of-joy:6333.
Historical references in discussion archives and sprint briefings
are preserved as-is.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clarify that every /pr-review invocation must start fresh — fetch,
check PRs, and re-read the diff even if the branch was reviewed
earlier in the same conversation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tickets with no team assignment caused start-sprint.sh to create
a spurious "sprint-N/None" worktree and Ptyxis tab. Filter at both
the SQL level (AND team IS NOT NULL) and Python level (if r['team']).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove severity tiers from PR reviews. Every comment must be addressed
before merge — no "suggestion" category that gets skipped. Teams can
push back on specific comments with a technical rationale; team lead
evaluates and can retract. Bar: "the reviewer was wrong" not "we don't
want to."
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Team worktree windows stay on their sprint branch. PR reviews run from
main. Updated step 9b to explicitly stop the team lead from spawning
reviewers — push the PR and wait for feedback instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass "claude /sprint-start" as the initial tmux command so each team
tab loads its briefing and spawns agents automatically — no manual
step needed after tabs open.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
start-sprint.sh now uses --tab for all teams (opens in active Ptyxis
window) instead of --new-window. No separate main tab — the caller
is already on main.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move start-sprint.sh into .claude/skills/sprint-start/scripts/ (was
standalone at parent directory level). Sprint-start Case B now calls
the script automatically after activating a sprint — creates ephemeral
worktrees and opens Ptyxis tabs for each active team.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Persistent worktrees (server, client, copy, audio, visual, ci, planning,
maintenance) caused agents crossing boundaries, stuck agents leaving
uncommitted work, and index.lock collisions. Replaced with ephemeral
sprint branches (sprint-{N}/{team}) and worktrees created on demand.
Changes:
- New start-sprint script replaces start-session (dynamic tabs per active team)
- Sprint teardown integrated into sprint-start skill (A1c step)
- SR_DB_PATH env var for database access from any directory
- CLAUDE.md team boundaries rewritten (scope-based, not directory-based)
- Agent Rule 0 updated to team scope dirs instead of worktree isolation
- PR review uses git show instead of cross-directory reads
- Briefing template updated for sprint-{N}/{team} branch naming
- Deleted worktree-update skill (obsolete)
- Removed WORKTREE_TEAM env var and cross-directory Read permissions
- All 8 persistent worktrees removed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents positional argument syntax and key rules for the ticket
CLI to prevent --title flag misuse and sqlite3 crashes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint 30 showed that grepping source files does not distinguish
committed code from uncommitted agent work. Added mandatory
git status + git diff --stat check from repo root before accepting
"already done" claims, and a warning about CWD path resolution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `list-systems` subcommand with --sector, --hop, --finished, --unfinished
filters. Also adds --sector flag to existing `unfinished` and `next` commands
for corridor-scoped queries during atlas authoring.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>