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
76 changes: 76 additions & 0 deletions .claude/hooks/session-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/sh
# SPDX-License-Identifier: MPL-2.0
#
# session-start.sh: configure SSH commit signing at Claude Code session start.
#
# Reads CLAUDE_SIGNING_KEY (base64 of an ed25519 private key, one line),
# CLAUDE_SIGNING_NAME and CLAUDE_SIGNING_EMAIL from the cloud environment.
# Writes ~/.ssh/id_ed25519_signing (mode 600) and ~/.ssh/allowed_signers,
# then sets signing config in the global git config (~/.gitconfig).
#
# Idempotent. Never prints the key. On any problem it prints a loud warning
# and exits 0, so the session still starts (unsigned-commit risk is reported,
# not hidden).

set -eu

# Cloud sessions only: on a workstation this would overwrite a real key file.
[ "${CLAUDE_CODE_REMOTE:-}" = "true" ] || exit 0

warn() {
printf '%s\n' "!!! WARNING: commit signing NOT configured: $1" \
"!!! Commits from this session will not carry the CLAUDE_SIGNING_KEY signature."
exit 0
}

missing=""
[ -n "${CLAUDE_SIGNING_KEY:-}" ] || missing="$missing CLAUDE_SIGNING_KEY"
[ -n "${CLAUDE_SIGNING_NAME:-}" ] || missing="$missing CLAUDE_SIGNING_NAME"
[ -n "${CLAUDE_SIGNING_EMAIL:-}" ] || missing="$missing CLAUDE_SIGNING_EMAIL"
[ -z "$missing" ] || warn "missing environment variable(s):$missing"

# git needs ssh-keygen to sign with gpg.format=ssh; the base image lacks it.
if ! command -v ssh-keygen >/dev/null 2>&1; then
{ apt-get install -y openssh-client || { apt-get update && apt-get install -y openssh-client; }; } \
>/dev/null 2>&1 || warn "ssh-keygen is missing and apt-get could not install openssh-client"
fi

ssh_dir="$HOME/.ssh"
key="$ssh_dir/id_ed25519_signing"
signers="$ssh_dir/allowed_signers"

umask 077
mkdir -p "$ssh_dir"
chmod 700 "$ssh_dir"

# Decode to a temp file, then move into place, so a bad value never leaves a
# half-written key. snip:prod: key material: no echo, no set -x, mode 600.
tmp="$key.tmp.$$"
trap 'rm -f "$tmp"' EXIT
printf '%s' "$CLAUDE_SIGNING_KEY" | base64 -d > "$tmp" 2>/dev/null \
|| warn "CLAUDE_SIGNING_KEY is not valid base64"
chmod 600 "$tmp"
pub=$(ssh-keygen -y -P '' -f "$tmp" 2>/dev/null) \
|| warn "CLAUDE_SIGNING_KEY is not an unencrypted OpenSSH private key"
case "$pub" in
ssh-ed25519\ *) ;;
*) warn "CLAUDE_SIGNING_KEY is not an ed25519 key" ;;
esac
mv -f "$tmp" "$key"
printf '%s\n' "$pub" > "$key.pub"
printf '%s namespaces="git" %s\n' "$CLAUDE_SIGNING_EMAIL" "$pub" > "$signers"
chmod 644 "$key.pub" "$signers"

# Global scope, so every repository in the session signs with this key. This
# overwrites the harness signer settings in ~/.gitconfig. gpg.ssh.program is
# reset to ssh-keygen because the harness points it at its own signer, which
# would ignore our key.
git config --global user.name "$CLAUDE_SIGNING_NAME"
git config --global user.email "$CLAUDE_SIGNING_EMAIL"
git config --global user.signingkey "$key"
git config --global gpg.format ssh
git config --global gpg.ssh.program ssh-keygen
git config --global gpg.ssh.allowedSignersFile "$signers"
git config --global commit.gpgsign true

echo "Commit signing configured (ssh, key $key, principal from CLAUDE_SIGNING_EMAIL)."
1 change: 1 addition & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"hooks":{"SessionStart":[{"hooks":[{"command":"\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start.sh","type":"command"}]}]}}
2 changes: 1 addition & 1 deletion .github/workflows/dogfood-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ jobs:
exit 1
fi
PLOCK="$RUNNER_TEMP/pending.lock"
if ! curl -fsSL --retry 3 --max-time 30 \
if ! curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 --max-time 30 \
"https://raw.githubusercontent.com/${CANON_REPO}/${head}/canon.lock" -o "$PLOCK"; then
echo "::error::could not fetch canon.lock at ${CANON_REPO}@${head:0:7}"
exit 1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/secret-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -353,13 +353,13 @@ jobs:
set -euo pipefail
rc=0
# Provider-specific patterns, plus assignment of a quoted literal to a
# *_TOKEN / *_KEY / *_SECRET / PASSWORD name (as in the estate canonical
# *_TOKEN / *_KEY / *_SECRET / PASSWORD name (as in the estate canonical # NOSONAR yaml:S2068: comment names the PASSWORD pattern the scanner detects; no credential
# reusable, metadatastician/standards@e064539
# .github/workflows/secret-scanner-reusable.yml). The value classes
# exclude '$', so ="${VAR}" and ="$VAR" never match. Only file names
# are listed, never the matched text.
SQ="'"
ASSIGN="[A-Z_]*(TOKEN|API_KEY|SECRET)[A-Z_]*=[\"${SQ}][A-Za-z0-9_./+=-]{16,}[\"${SQ}]|PASSWORD=[\"${SQ}][^\"${SQ}\$]{6,}[\"${SQ}]"
ASSIGN="[A-Z_]*(TOKEN|API_KEY|SECRET)[A-Z_]*=[\"${SQ}][A-Za-z0-9_./+=-]{16,}[\"${SQ}]|PASSWORD=[\"${SQ}][^\"${SQ}\$]{6,}[\"${SQ}]" # NOSONAR yaml:S2068: scanner regex matching PASSWORD= literals, not a credential
PROVIDER='ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{82}|glpat-[A-Za-z0-9_-]{20,}|AKIA[0-9A-Z]{16}|-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----'
git grep -IlE "(${PROVIDER}|${ASSIGN})" > "$RUNNER_TEMP/hits.txt" || rc=$?
# git grep exits 1 when nothing matches; above 1 is an error.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/security-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
fi

# Block HTTP URLs (except localhost)
HTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" --include="*.kyaml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true)
HTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" --include="*.kyaml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true) # NOSONAR githubactions:S5332: regex that detects http:// URLs, not a request
if [ -n "$HTTP_URLS" ]; then
echo "⚠️ HTTP URLs found. Use HTTPS:"
echo "$HTTP_URLS"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/verdict-grid-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:

- name: Checkout trusted default-branch reporter
if: steps.source.outputs.pr != ''
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # NOSONAR githubactions:S7631: ref is the default branch, not PR code
with:
ref: ${{ github.event.repository.default_branch }}
persist-credentials: false
Expand All @@ -68,7 +68,7 @@ jobs:

- name: Checkout pinned renderer
if: steps.source.outputs.pr != ''
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # NOSONAR githubactions:S7631: fixed trusted repo at a pinned SHA, not fork code
with:
repository: metadatastician/standards
ref: e064539116c2dcfdf282a4749dbd58c69961c7e6
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ Thumbs.db
.direnv/

# Agent / local session artifacts (Claude Code worktrees, scratch) — never commit
.claude/
.claude/*
!.claude/settings.json
!.claude/hooks/

# Build
target/
Expand Down
2 changes: 1 addition & 1 deletion PROOF-STATUS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ threads (choreographic-types A-3), occupancy has two theorems of its own.
== Housekeeping done with this commit

* `scripts/check-agda.sh` is the Agda gate (the template's `check-proofs.sh` is untouched).
* README title `{{PROJECT_NAME}}` replaced.
* README title placeholder (PROJECT_NAME) replaced.
* `src/session_ir` (Python) removed; the v0 stepper is now `src/julia/`
(SessionIR, Julia 1.10, standard library only), ported 2026-10-12 and
verified against the Python on all 14 pinned fixtures and on
Expand Down
2 changes: 1 addition & 1 deletion build/just/provision-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ cmd_heal() {
[ -f mise.lock ] || { $T mise lock 2>/dev/null && info "mise.lock generated"; }
fi
if printf '%s\n' "${LANGS[@]}" | grep -qx elixir && have mix; then mix deps.get >/dev/null 2>&1 && info "mix deps fetched"; fi
if printf '%s\n' "${LANGS[@]}" | grep -qx bun && have bun; then bun install >/dev/null 2>&1 && info "bun deps installed"; fi
if printf '%s\n' "${LANGS[@]}" | grep -qx bun && have bun; then bun install --ignore-scripts >/dev/null 2>&1 && info "bun deps installed"; fi
if printf '%s\n' "${LANGS[@]}" | grep -qx julia && have julia; then julia --project=. -e 'using Pkg; Pkg.instantiate()' >/dev/null 2>&1 && info "julia deps instantiated"; fi
local hook=build/just/heal-local.sh
[ -f "$hook" ] && { info "running $hook"; bash "$hook" || true; }
Expand Down
6 changes: 2 additions & 4 deletions docs/EXPLAINME.adoc
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
// SPDX-License-Identifier: CC-BY-SA-4.0
// Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
= RSR Template Repo - Explainme
= occupancy-types — claims to files
image:https://img.shields.io/badge/License-MPL_2.0-blue.svg[License: MPL-2.0,link="https://opensource.org/licenses/MPL-2.0"]

:toc:
:icons: font

This file explains how the key template claims map to real files.

= occupancy-types — claims to files

Project claims (ULTRAPLAN R0-B + R1). Receipts taxonomy: *TESTED* (command,
toolchain/version, and result recorded here), *UNVERIFIED* (code + exact
command; execution or an independent fixture is still pending), *CONJECTURE*
Expand Down Expand Up @@ -145,7 +143,7 @@ are pending.
provenance, and axiom/library record, followed by the policy-required
Mathesis initial audit. This Lean receipt does not provide those items.

= RSR template claims
== RSR template claims

The sections below describe the scaffold this project is built on.

Expand Down
4 changes: 4 additions & 0 deletions docs/architecture/REPOSITORY-MAP.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ predecessors did.
| yes
| code-hygiene gate allowlist; template scaffolds are seams, not debt

| `.claude/`
| optional
| Claude Code project state (checkpoints, history) — created by the tool itself

| `.clinerules`
| yes
| AI editor rules. Cline reads them from the project ROOT, so the copies formerly under .machine_readable/ai/ were inert (.cursorrules and .windsurfrules were retired 2026-10-26)
Expand Down
1 change: 0 additions & 1 deletion docs/recon/ULTRA-PLAN-2026-10-04.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ toc::[]
| *Gate fixed:* the action-pinning gate now exits 0 for the first time
| `node scripts/check-action-pinning.js` → *exit 0*, "all action refs are pinned".
(Two refs were unpinned on `main` since they were introduced; see A8.)
|===

| The outage reproduces on this branch, in the current hour
| The push of `d5caaca` created run `37236457077` ("Push email notification", 21:31:42Z)
Expand Down
22 changes: 1 addition & 21 deletions examples/session_ir/manifest.json
Original file line number Diff line number Diff line change
@@ -1,21 +1 @@
{
"comment": "occupancy-types Session IR example manifest (ULTRAPLAN Phase 1). Accept entries pin the expected judgment A|r, measured communication steps and peak live bytes; reject entries pin the expected error code. Runner: julia --project=src/julia src/julia/bin/sessionir.jl test examples/session_ir/manifest.json",
"examples": [
{"file": "accept_unit.sir", "expect": "accept", "type": "Unit", "grade": 0, "steps": 0, "peak_live": 0},
{"file": "accept_send_recv.sir", "expect": "accept", "type": "Unit", "grade": 2, "steps": 2, "peak_live": 0},
{"file": "accept_seq_add.sir", "expect": "accept", "type": "Unit", "grade": 4, "steps": 4, "peak_live": 0},
{"file": "accept_choice_max.sir", "expect": "accept", "type": "Unit", "grade": 5, "steps": 4, "peak_live": 0},
{"file": "accept_choice_expensive.sir","expect": "accept", "type": "Unit", "grade": 6, "steps": 6, "peak_live": 0},
{"file": "accept_buf_delegation.sir", "expect": "accept", "type": "Unit", "grade": 2, "steps": 2, "peak_live": 4},
{"file": "accept_pair_drop.sir", "expect": "accept", "type": "Unit", "grade": 0, "steps": 0, "peak_live": 6},
{"file": "accept_pair_drop_send_recv.sir", "expect": "accept", "type": "Unit", "grade": 2, "steps": 2, "peak_live": 6},
{"file": "accept_annotated.sir", "expect": "accept", "type": "Unit", "grade": 2, "steps": 2, "peak_live": 0},
{"file": "reject_double_send.sir", "expect": "reject", "error": "E_PROTOCOL"},
{"file": "reject_drop_then_send.sir", "expect": "reject", "error": "E_USE_AFTER_DROP"},
{"file": "reject_protocol_mismatch.sir","expect": "reject", "error": "E_PROTOCOL"},
{"file": "reject_close_before_end.sir","expect": "reject", "error": "E_CLOSE_NOT_END"},
{"file": "reject_double_free.sir", "expect": "reject", "error": "E_DOUBLE_FREE"},
{"file": "reject_leak.sir", "expect": "reject", "error": "E_LEAK"},
{"file": "reject_alias.sir", "expect": "reject", "error": "E_ALIAS"}
]
}
{"comment":"occupancy-types Session IR example manifest (ULTRAPLAN Phase 1). Accept entries pin the expected judgment A|r, measured communication steps and peak live bytes; reject entries pin the expected error code. Runner: julia --project=src/julia src/julia/bin/sessionir.jl test examples/session_ir/manifest.json","examples":[{"expect":"accept","file":"accept_unit.sir","grade":0,"peak_live":0,"steps":0,"type":"Unit"},{"expect":"accept","file":"accept_send_recv.sir","grade":2,"peak_live":0,"steps":2,"type":"Unit"},{"expect":"accept","file":"accept_seq_add.sir","grade":4,"peak_live":0,"steps":4,"type":"Unit"},{"expect":"accept","file":"accept_choice_max.sir","grade":5,"peak_live":0,"steps":4,"type":"Unit"},{"expect":"accept","file":"accept_choice_expensive.sir","grade":6,"peak_live":0,"steps":6,"type":"Unit"},{"expect":"accept","file":"accept_buf_delegation.sir","grade":2,"peak_live":4,"steps":2,"type":"Unit"},{"expect":"accept","file":"accept_pair_drop.sir","grade":0,"peak_live":6,"steps":0,"type":"Unit"},{"expect":"accept","file":"accept_pair_drop_send_recv.sir","grade":2,"peak_live":6,"steps":2,"type":"Unit"},{"expect":"accept","file":"accept_annotated.sir","grade":2,"peak_live":0,"steps":2,"type":"Unit"},{"error":"E_PROTOCOL","expect":"reject","file":"reject_double_send.sir"},{"error":"E_USE_AFTER_DROP","expect":"reject","file":"reject_drop_then_send.sir"},{"error":"E_PROTOCOL","expect":"reject","file":"reject_protocol_mismatch.sir"},{"error":"E_CLOSE_NOT_END","expect":"reject","file":"reject_close_before_end.sir"},{"error":"E_DOUBLE_FREE","expect":"reject","file":"reject_double_free.sir"},{"error":"E_LEAK","expect":"reject","file":"reject_leak.sir"},{"error":"E_ALIAS","expect":"reject","file":"reject_alias.sir"}]}
8 changes: 4 additions & 4 deletions occupancy-types_chora.deed
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@
:last-updated "2026-11-12"
:parent "hyperpolymath/rsr-template-repo"
; template tip at mint
:parent-pin "840ac2509f28a176fe7e2c991b909375654164dc"
:parent-pin "2f54c7b53cabb0b49c10a2653815e1a1ba9a730c"
:role "minted-repo"
:stack "unspecified"
:direction "generated-from-core"
Expand All @@ -1104,16 +1104,16 @@
(paths
:added ("examples/session_ir/" "src/OccupancyTypes/" "src/julia/" "src/occ/" "src/stackcert/" "tests/reject/" ".github/workflows/lean4-manifest.yml" ".github/workflows/proofs.yml" ".github/workflows/session-ir.yml" "PROOF-STATUS.adoc" "ULTRAPLAN.md" "docs/DECISION-001-python-stepper.adoc" "docs/OPERATIONAL-MODEL.md" "docs/glossary.adoc" "docs/recon/A1-ACTIONS-RUNBOOK.adoc" "docs/recon/COORDINATED-PLAN-2026-10-04.adoc" "docs/recon/TYPE-FAMILY-POSITION-2026-10-04.adoc" "docs/recon/ULTRA-PLAN-2026-10-04.adoc" "docs/reports/session-2026-09-27.adoc" "docs/retraction-ledger.adoc" "docs/status/HYPATIA-GATE.adoc" "occupancy-types.agda-lib" "scripts/check-agda.sh" "scripts/check.sh" "scripts/fetch-siblings.sh" "scripts/kill-test-audit.jl" "scripts/scan-postulates.pl" "tests/check_agda_find_failure_test.sh" "tests/run_stackcert.sh" "tests/scan_postulates_test.sh" "verification/proofs/lean4/CostStateSeparation.lean")
:removed ("archetypes/" "build/docs-seed/" "build/templates/" "rsr-template-repo_chora.deed")
:diverged ("occupancy-types_chora.deed" "docs/status/ROADMAP.adoc" "CLAUDE.md" "docs/architecture/REPOSITORY-MAP.adoc" "README.adoc" "CITATION.cff" "CHANGELOG.adoc" "LICENSE" "Justfile" ".gitignore" ".machine_readable/root-allow.txt" ".github/workflows/actions.lock" ".github/workflows/push-email-notify.yml" ".github/workflows/release.yml" ".github/workflows/sonarqube.yml" "docs/EXPLAINME.adoc" "scripts/check-no-md-in-docs.sh" "verification/proofs/idris2/MANIFEST" "verification/proofs/lean4/MANIFEST")))
:diverged ("occupancy-types_chora.deed" "docs/status/ROADMAP.adoc" "CLAUDE.md" "docs/architecture/REPOSITORY-MAP.adoc" "README.adoc" "CITATION.cff" "CHANGELOG.adoc" "LICENSE" "Justfile" ".gitignore" ".machine_readable/root-allow.txt" ".github/workflows/actions.lock" ".github/workflows/push-email-notify.yml" ".github/workflows/release.yml" ".github/workflows/sonarqube.yml" "docs/EXPLAINME.adoc" "scripts/check-no-md-in-docs.sh" "verification/proofs/idris2/MANIFEST" "verification/proofs/lean4/MANIFEST" "mise.toml")))
; provenance — what this repo was minted FROM. Written once, at mint,
; by build/just/repo-init.just. Tools that want "what is this repo" read
; the rest of the deed; tools that want "where did it come from" read this.
(provenance
:minted-at "2026-11-12"
:template-repo "hyperpolymath/rsr-template-repo"
:template-branch "main"
:template-commit "840ac2509f28a176fe7e2c991b909375654164dc"
:template-tree "a7e2cb8e1d6e868ed56f00effefb6417b396f6a7"
:template-commit "2f54c7b53cabb0b49c10a2653815e1a1ba9a730c"
:template-tree "1d693c668dd22ff03a05ba8a1b79f1ebf1577787"
; Contract: branches this repo is EXPECTED to carry beyond the default.
; Empty means default-only. A mint must never inherit template work
; branches (coderabbit/, chore/, bot-task or stale branches) — that is
Expand Down
6 changes: 3 additions & 3 deletions scripts/uuid5-url.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ set -euo pipefail
[ $# -eq 1 ] || { echo "usage: uuid5-url.sh NAME" >&2; exit 2; }

sha1() {
if command -v sha1sum >/dev/null 2>&1; then sha1sum
elif command -v shasum >/dev/null 2>&1; then shasum -a 1
elif command -v openssl >/dev/null 2>&1; then openssl dgst -sha1 -r
if command -v sha1sum >/dev/null 2>&1; then sha1sum # NOSONAR shell:S4790: RFC 9562 mandates SHA-1 for UUIDv5
elif command -v shasum >/dev/null 2>&1; then shasum -a 1 # NOSONAR shell:S4790: RFC 9562 mandates SHA-1 for UUIDv5
elif command -v openssl >/dev/null 2>&1; then openssl dgst -sha1 -r # NOSONAR shell:S4790: RFC 9562 mandates SHA-1 for UUIDv5
else echo "uuid5-url.sh: needs sha1sum, shasum or openssl" >&2; return 2
fi
}
Expand Down
6 changes: 1 addition & 5 deletions src/stackcert/lake-manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{"version": "1.1.0",
"packagesDir": ".lake/packages",
"packages": [],
"name": "stackcert",
"lakeDir": ".lake"}
{"lakeDir":".lake","name":"stackcert","packages":[],"packagesDir":".lake/packages","version":"1.1.0"}
12 changes: 10 additions & 2 deletions tests/e2e/template_instantiation_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,16 @@
# Local ignored agent state is not part of the template product. A filesystem
# copy sees it anyway, unlike a real GitHub-template instantiation, and can make
# the placeholder gate judge unrelated nested worktrees. Remove it from the
# fixture before exercising the mint.
rm -rf "$TEST_REPO_PATH/.claude"
# fixture before exercising the mint. Remove only the IGNORED paths: tracked
# files there (.claude/settings.json, .claude/hooks/) are template content, and
# dropping them gives a tree that matches no template commit.
git -C "$TEMPLATE_ROOT" ls-files -z --others --ignored --exclude-standard --directory -- .claude \
| (cd "$TEST_REPO_PATH" && xargs -0 -r rm -rf --)
CLEAN_STATUS=("${PIPESTATUS[@]}")
if [ "${CLEAN_STATUS[0]}" -ne 0 ] || [ "${CLEAN_STATUS[1]}" -ne 0 ]; then

Check failure on line 100 in tests/e2e/template_instantiation_test.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_occupancy-types&issues=AaHQqet9PfPtcKV5lTQ4&open=AaHQqet9PfPtcKV5lTQ4&pullRequest=22

Check failure on line 100 in tests/e2e/template_instantiation_test.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_occupancy-types&issues=AaHQqet9PfPtcKV5lTQ5&open=AaHQqet9PfPtcKV5lTQ5&pullRequest=22
log_error "could not remove ignored .claude/ state from the fixture"
exit 1
fi

# Remove .git directory for clean state, then re-init as the INSTANTIATED repo.
#
Expand Down
Loading
Loading