Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2d91f75
fix(renderer): explain safe manifest recovery
amasiye Sep 22, 2026
ee9ca53
fix(console): preserve actor identities from generation through startup
amasiye Sep 23, 2026
b71ee5c
test(console): make startup fixtures portable across checkouts
amasiye Sep 23, 2026
265fa94
fix(console): repair released actor references during validation
amasiye Sep 23, 2026
a166d82
fix(console): stop planning migration for unrelated validation
amasiye Sep 24, 2026
36d0556
fix(console): remove automatic renderer rebuilds from play
amasiye Sep 24, 2026
fc3f1da
refactor(console)!: run ichiloto upgrade as a numbered project format…
amasiye Sep 26, 2026
18beccf
feat(console): add the two-column cell step to the format chain
amasiye Sep 26, 2026
8d3c965
feat(console): scaffold format 2 projects with two-column cells
amasiye Sep 26, 2026
1cc6295
feat(console): stop play and validate on an outdated project format
amasiye Sep 26, 2026
a329aa1
docs(console): document the upgrade format chain and its report
amasiye Sep 26, 2026
c0a62cd
revert(console)!: withdraw the two-column cell upgrade step
amasiye Sep 27, 2026
e87dee6
feat(generate): create a map with its kind
amasiye Sep 30, 2026
5633eb2
build(deps): require the Editor at dev-develop during the 0.6 cycle
amasiye Sep 30, 2026
4067b53
feat(battle): choose the arena's renderer as play chooses the game's
amasiye Oct 2, 2026
0298503
feat(battle): set up the battle test party with --member
amasiye Oct 2, 2026
3cd779e
feat(battle): give a battle test member commands, skills and summons
amasiye Oct 2, 2026
b63d832
fix(battle): refuse battle test loadouts in simulations, and name eve…
amasiye Oct 2, 2026
13491a8
feat(edit): open a project in the GUI editor with edit --gui
amasiye Oct 3, 2026
caf5812
feat(edit): tell the editor which console opened it, for playtests
amasiye Oct 3, 2026
c04631d
feat(new): scaffold enemies.php as the loader of Enemies/ records
amasiye Oct 4, 2026
a37dcb1
feat(scaffold): author new projects' skills as records that skills.ph…
amasiye Oct 4, 2026
187797d
feat(scaffold): author new projects' items, weapons and armors as rec…
amasiye Oct 4, 2026
a2fb034
feat(battle): choose the battle test arena with --arena
amasiye Oct 4, 2026
c13bf82
feat(edit): run the GUI editor from its macOS bundle, named Ichiloto
amasiye Oct 4, 2026
3771d0e
docs(battle): show a current summon in the --member examples
amasiye Oct 5, 2026
2818345
feat(battle): start from the project's battle test party and arena
amasiye Oct 5, 2026
8de5de4
fix(governance): remove direct-main publishing allowances
amasiye Oct 8, 2026
421ea10
docs(governance): remove dependency on excluded shared repository
amasiye Oct 8, 2026
e5f71fc
docs: remove universal workflow scope beyond Andrew-created develop
amasiye Oct 8, 2026
a73eb85
chore(governance): preserve existing develop publishing safeguards
amasiye Oct 9, 2026
c3136d7
chore(governance): merge published develop safeguards without rewriti…
amasiye Oct 9, 2026
c558aec
feat(play): add explicit startup and owned terminal sessions
amasiye Oct 11, 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
22 changes: 22 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
set -eu

branch=$(git symbolic-ref --quiet HEAD) || {
printf '%s\n' 'Commit blocked: work must be on develop or a local working branch, not detached HEAD.' >&2
exit 1
}
case "$branch" in
refs/heads/main)
printf '%s\n' 'Commit blocked: main receives changes only through a GitHub PR from develop.' >&2
exit 1
;;
refs/heads/release/*)
printf '%s\n' 'Commit blocked: release branches are Andrew-only.' >&2
exit 1
;;
refs/heads/*) ;;
*)
printf '%s\n' 'Commit blocked: cannot establish a local working branch.' >&2
exit 1
;;
esac
22 changes: 22 additions & 0 deletions .githooks/pre-merge-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
set -eu

branch=$(git symbolic-ref --quiet HEAD) || {
printf '%s\n' 'Commit blocked: work must be on develop or a local working branch, not detached HEAD.' >&2
exit 1
}
case "$branch" in
refs/heads/main)
printf '%s\n' 'Commit blocked: main receives changes only through a GitHub PR from develop.' >&2
exit 1
;;
refs/heads/release/*)
printf '%s\n' 'Commit blocked: release branches are Andrew-only.' >&2
exit 1
;;
refs/heads/*) ;;
*)
printf '%s\n' 'Commit blocked: cannot establish a local working branch.' >&2
exit 1
;;
esac
31 changes: 31 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh
set -eu

deny() {
printf '%s\n' "Push blocked: $1" >&2
printf '%s\n' 'Only an authorized fast-forward from local develop to existing remote develop is eligible.' >&2
printf '%s\n' 'Main requires a GitHub PR from develop. Do not bypass this guard through options, config, APIs or UI.' >&2
exit 1
}

validate_oid() {
case "$1" in ''|*[!0-9a-fA-F]*) return 1 ;; esac
case ${#1} in 40|64) return 0 ;; *) return 1 ;; esac
}

updates=0
while read -r local_ref local_oid remote_ref remote_oid extra; do
[ -z "$extra" ] || deny 'malformed ref update.'
[ "$remote_ref" = refs/heads/develop ] || deny "$remote_ref is not develop."
[ "$local_ref" = refs/heads/develop ] || deny 'the source must be local refs/heads/develop.'
validate_oid "$local_oid" && validate_oid "$remote_oid" || deny 'malformed object ID.'
case "$local_oid" in *[!0]*) ;; *) deny 'branch deletion is forbidden.' ;; esac
case "$remote_oid" in *[!0]*) ;; *) deny 'remote branch creation needs Andrew’s explicit authorization.' ;; esac
current_oid=$(git rev-parse --verify refs/heads/develop) || deny 'local develop is missing.'
[ "$local_oid" = "$current_oid" ] || deny 'the source object is not the current local develop head.'
git cat-file -e "$remote_oid^{commit}" 2>/dev/null || deny 'remote develop commit is unavailable locally; fetch it and reassess.'
git cat-file -e "$local_oid^{commit}" 2>/dev/null || deny 'local develop is not a known commit.'
git merge-base --is-ancestor "$remote_oid" "$local_oid" || deny 'develop update would rewrite remote history.'
updates=$((updates + 1))
done
[ "$updates" -gt 0 ] || deny 'no ref updates were supplied; the destination cannot be established.'
140 changes: 140 additions & 0 deletions .githooks/test-guards.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/bin/sh
set -eu

kit=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
tmp=$(mktemp -d "${TMPDIR:-/tmp}/ichiloto-guards.XXXXXX")
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
work="$tmp/work"
remote="$tmp/remote.git"
checks=0

pass() { checks=$((checks + 1)); }
fail() { printf 'FAIL: %s\n' "$1" >&2; cat "$tmp/log" >&2; exit 1; }
expect_failure() {
label=$1
shift
if "$@" >"$tmp/log" 2>&1; then fail "$label unexpectedly succeeded"; fi
pass
}
expect_success() {
label=$1
shift
if ! "$@" >"$tmp/log" 2>&1; then fail "$label failed"; fi
pass
}
check_update() {
expected=$1
label=$2
shift 2
printf '%s\n' "$@" >"$tmp/input"
if (cd "$work" && "$kit/.githooks/pre-push" origin "$remote" <"$tmp/input") >"$tmp/log" 2>&1; then
actual=allow
else
actual=deny
fi
[ "$actual" = "$expected" ] || fail "$label: expected $expected, got $actual"
pass
}

git init --quiet --initial-branch=main "$work"
git -C "$work" config user.name 'Governance fixture'
git -C "$work" config user.email 'governance-fixture@example.invalid'
printf 'seed\n' >"$work/content"
git -C "$work" add content
git -C "$work" commit --quiet -m 'test: seed fixture before installing guards'
seed=$(git -C "$work" rev-parse HEAD)
git -C "$work" branch develop
git clone --quiet --bare "$work" "$remote"
git -C "$work" remote add origin "$remote"
cp -R "$kit/.githooks" "$work/.githooks"
mkdir -p "$work/scripts"
cp "$kit/scripts/install-git-guards.sh" "$work/scripts/"

expect_success 'initial install' git -C "$work" -c core.hooksPath=.git/hooks status --short
(cd "$work" && ./scripts/install-git-guards.sh) >"$tmp/log" 2>&1 || fail 'initial guard installation'
pass
first_target=$(readlink "$work/.git/hooks/pre-push")
(cd "$work" && ./scripts/install-git-guards.sh) >"$tmp/log" 2>&1 || fail 'idempotent guard installation'
[ "$(readlink "$work/.git/hooks/pre-push")" = "$first_target" ] || fail 'installer replaced existing guard symlink'
pass

printf 'forbidden\n' >"$work/forbidden-main"
git -C "$work" add forbidden-main
expect_failure 'main commit' git -C "$work" commit --quiet -m 'test: must be blocked'
[ "$(git -C "$work" rev-parse HEAD)" = "$seed" ] || fail 'main commit changed HEAD'
pass
git -C "$work" reset --quiet
rm "$work/forbidden-main"

git -C "$work" switch --quiet develop
printf 'develop\n' >>"$work/content"
git -C "$work" add content
expect_success 'develop commit' git -C "$work" commit --quiet -m 'test: accepted develop fixture'
develop=$(git -C "$work" rev-parse HEAD)
git -C "$work" switch --quiet main
expect_failure 'main merge commit' git -C "$work" merge --no-ff -m 'test: blocked main merge' develop
[ "$(git -C "$work" rev-parse HEAD)" = "$seed" ] || fail 'main merge changed HEAD'
pass
git -C "$work" merge --abort
expect_failure 'main no-op push' git -C "$work" push origin main
git -C "$work" switch --quiet develop
expect_success 'existing develop fast-forward push' git -C "$work" push origin develop
[ "$(git --git-dir="$remote" rev-parse develop)" = "$develop" ] || fail 'remote develop did not advance'
pass

zero=0000000000000000000000000000000000000000
unknown=1111111111111111111111111111111111111111
check_update allow 'develop fast-forward' "refs/heads/develop $develop refs/heads/develop $seed"
check_update allow 'develop unchanged input' "refs/heads/develop $develop refs/heads/develop $develop"
check_update deny 'main update' "refs/heads/develop $develop refs/heads/main $seed"
check_update deny 'main no-op' "refs/heads/main $seed refs/heads/main $seed"
check_update deny 'main deletion' "(delete) $zero refs/heads/main $seed"
check_update deny 'develop deletion' "(delete) $zero refs/heads/develop $develop"
check_update deny 'develop creation' "refs/heads/develop $develop refs/heads/develop $zero"
check_update deny 'unknown remote object' "refs/heads/develop $develop refs/heads/develop $unknown"
check_update deny 'feature source into develop' "refs/heads/feature/test $develop refs/heads/develop $seed"
check_update deny 'mixed destination push' "refs/heads/develop $develop refs/heads/develop $seed" "refs/heads/develop $develop refs/heads/main $seed"
check_update deny 'false develop object' "refs/heads/develop $seed refs/heads/develop $seed"
check_update deny 'malformed update' "refs/heads/develop not-a-hash refs/heads/develop $seed"
check_update deny 'extra input field' "refs/heads/develop $develop refs/heads/develop $seed surprise"
for ref in refs/heads/feature/test refs/heads/fix/test refs/heads/release/1.0.0 refs/tags/v1.0.0; do
check_update deny "forbidden destination $ref" "refs/heads/develop $develop $ref $seed"
done

git -C "$work" update-ref refs/heads/main "$develop"
expect_failure 'actual direct main push' git -C "$work" push origin main
[ "$(git --git-dir="$remote" rev-parse main)" = "$seed" ] || fail 'blocked main push mutated remote'
pass
git -C "$work" update-ref refs/heads/develop "$seed"
expect_failure 'actual force rewrite of develop' git -C "$work" push --force origin develop
[ "$(git --git-dir="$remote" rev-parse develop)" = "$develop" ] || fail 'blocked rewrite mutated remote'
pass
git -C "$work" update-ref refs/heads/develop "$develop"
expect_failure 'actual remote working branch creation' git -C "$work" push origin develop:feature/test
expect_failure 'actual remote develop deletion' git -C "$work" push origin :develop
expect_failure 'actual mixed develop/main push' git -C "$work" push origin develop main

git -C "$work" switch --quiet --detach "$develop"
expect_failure 'detached commit' git -C "$work" commit --allow-empty --quiet -m 'test: detached must be blocked'
git -C "$work" switch --quiet -c release/1.0.0
expect_failure 'release commit' git -C "$work" commit --allow-empty --quiet -m 'test: release must be blocked'
git -C "$work" switch --quiet -c feature/test
expect_success 'local working branch commit' git -C "$work" commit --allow-empty --quiet -m 'test: local working branch is allowed'

# The configured hooks directory is preserved; unknown hooks block all installation.
git -C "$work" config core.hooksPath custom-hooks
mkdir "$work/custom-hooks"
printf '#!/bin/sh\nexit 0\n' >"$work/custom-hooks/pre-push"
chmod +x "$work/custom-hooks/pre-push"
cp "$work/custom-hooks/pre-push" "$tmp/existing-hook"
expect_failure 'unknown existing hook' sh -c 'cd "$1" && ./scripts/install-git-guards.sh' sh "$work"
cmp -s "$tmp/existing-hook" "$work/custom-hooks/pre-push" || fail 'installer changed unrelated hook'
[ ! -e "$work/custom-hooks/pre-commit" ] || fail 'blocked install partially changed hook directory'
[ "$(git -C "$work" config core.hooksPath)" = custom-hooks ] || fail 'installer changed core.hooksPath'
pass
rm "$work/custom-hooks/pre-push"
ln -s "$work/.githooks/pre-push" "$work/custom-hooks/pre-push"
expect_success 'configured hooks directory install' sh -c 'cd "$1" && ./scripts/install-git-guards.sh' sh "$work"
[ "$(git -C "$work" config core.hooksPath)" = custom-hooks ] || fail 'configured path was not retained'
pass
printf 'Passed %s guard and installer checks using real commits, merges and local bare push destinations.\n' "$checks"
9 changes: 9 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Read `AGENTS.md` and `GIT_WORKFLOW.md` before acting. Andrew's develop-to-main
rule applies only where he has created a `develop` branch. This repository has
that existing branch: no direct commits, local merges or pushes to `main`.
All changes integrate into `develop` and reach `main` only through a
same-repository develop-to-main PR. Repositories found without Andrew-created
`develop` are outside this remediation and must be left alone; neither creating
that branch nor direct-main publishing is authorized by that exclusion.
Keep explicit branch-publication, deletion and history-rewrite permissions.
No historical private-repository exception grants permission.
12 changes: 12 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Change and validation

Describe the resulting behavior, tests run, and relevant limits.

## Git workflow

- [ ] I read `AGENTS.md` and `GIT_WORKFLOW.md` and preserved existing work.
- [ ] I confirmed Andrew created `develop` in this repository; the develop-to-main rule applies within that scope, and repositories without it are left alone.
- [ ] In this existing-develop repository, a PR into `main` comes from its `develop`.
- [ ] Any working branch here feeds `develop`; its publication has explicit approval.
- [ ] No direct-main commit/local merge/push here, unauthorized branch deletion or history rewrite; exclusion of other repositories grants no publishing permission.
- [ ] Removed, disabled or narrowed behavior is named plainly.
35 changes: 35 additions & 0 deletions .github/workflows/git-governance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Git workflow governance

on:
pull_request_target:
branches: [main]
types: [opened, synchronize, reopened, edited, ready_for_review]

permissions:
contents: read

jobs:
validate-develop-source:
name: Validate develop source
runs-on: ubuntu-latest
steps:
- name: Require same-repository develop for main
env:
EXPECTED_REPOSITORY: ${{ github.repository }}
run: |
python3 - <<'PY'
import json, os, sys
with open(os.environ['GITHUB_EVENT_PATH'], encoding='utf-8') as event_file:
pr = json.load(event_file)['pull_request']
head = pr.get('head') or {}
head_repo = head.get('repo') or {}
valid = (
pr.get('base', {}).get('ref') == 'main'
and head.get('ref') == 'develop'
and head_repo.get('full_name') == os.environ['EXPECTED_REPOSITORY']
)
if not valid:
print('Main accepts only a PR from this repository\'s develop branch.', file=sys.stderr)
sys.exit(1)
print('Verified: same-repository develop -> main.')
PY
17 changes: 17 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Repository agent instructions

## Binding Git workflow

Read [GIT_WORKFLOW.md](GIT_WORKFLOW.md) before work, after compaction and before
publishing. On Andrew's workstation also read the original
`/Users/andrewmasiye/.codex/AGENTS.md`. Andrew's develop-to-main rule applies
only where he has created a `develop` branch. This repository has that existing
branch: NEVER commit, merge locally or push directly to `main`, including private
documentation. Changes integrate into `develop`; `main` receives only a PR from
this repository's `develop`.
Repositories found without Andrew-created `develop` are outside this remediation
and must be left alone; do not create that branch or infer direct-main permission.
Remote working branches, history rewrites and branch deletion require explicit
scoped authorization. Within the existing-develop scope, prior direct-main
exception claims are superseded by Andrew's 2026-10-08 rule.
Install the tracked Git guards before committing or publishing here.
11 changes: 11 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Claude instructions

Read `AGENTS.md` and `GIT_WORKFLOW.md` in full before work, after compaction
and before publishing. Andrew's develop-to-main rule applies only where he
has created a `develop` branch. This repository has that existing branch:
no direct-main commits, local merges or pushes; all main changes use a
same-repository `develop` -> `main` PR. Repositories found without that branch
are outside this remediation and must be left alone. That exclusion does not
authorize creating `develop` or publishing directly to `main`. Never infer an
exception from historical messages; retain all explicit branch-publication,
deletion and history-rewrite permission requirements.
Loading
Loading