Skip to content

Add business harnesses, bounded loops, and peer CEO–CTO leadership #31

Add business harnesses, bounded loops, and peer CEO–CTO leadership

Add business harnesses, bounded loops, and peer CEO–CTO leadership #31

Workflow file for this run

name: compliance
on:
push:
branches: [main, series-a]
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
org-chart:
name: The company audits itself (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: The plugin command passes strict validation (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
npm install --global @anthropic-ai/claude-code@2.1.252
claude plugin validate --strict .claude-plugin/plugin.json
- name: Every employee has a valid job description (macOS and Linux)
if: runner.os != 'Windows'
run: python3 scripts/validate.py
- name: Every employee has a valid job description (Windows)
if: runner.os == 'Windows'
run: python scripts/validate.py
- name: The CLI can brief every department (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: |
chmod +x bin/company
for dept in developers designers marketing social-media finance small-business legal sales; do
count=$(./bin/company "$dept" "ci smoke test" --print | grep -c '^----- EMPLOYEE:')
echo "$dept -> $count employees"
[ "$count" -eq 6 ] || { echo "::error::$dept composed $count employees, expected 6"; exit 1; }
done
brief_output="$(./bin/company brief "ci smoke test" --print)"
[[ "$brief_output" == *'CEO Operating Manual'* ]]
./bin/company roster > /dev/null
./bin/company help > /dev/null
[ "$(./bin/company version)" = "company v1.5.0" ]
- name: A closed pipe ends the CLI quietly (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: |
set -eu
err="$RUNNER_TEMP/broken-pipe.err"
# Node, .NET and the Actions runner itself ignore SIGPIPE and hand that
# SIG_IGN to every child, so a reader leaving early reaches the CLI as
# EPIPE rather than as a signal. It must still end the way the default
# SIGPIPE would - silently, with 141 - and never as a bash write error.
probe() {
set +e +o pipefail
trap '' PIPE
./bin/company "$@" 2>"$err" | head -1 > /dev/null
echo "${PIPESTATUS[0]}"
}
# Bigger than any pipe buffer (64 KiB on Linux, 16 KiB on macOS), so the
# writer is certain to still be writing once the reader is gone.
padding="$(head -c 60000 < /dev/zero | tr '\0' x)"
: > "$err"
status="$(probe developers "$padding" --print)"
[ "$status" = 141 ] || { echo "::error::closed pipe: CLI exited $status, expected 141"; exit 1; }
[ ! -s "$err" ] || { echo "::error::closed pipe: CLI wrote to stderr"; cat "$err" >&2; exit 1; }
# The short commands may finish inside the buffer; either way, no noise.
for args in "roster" "help" "team" "version" "brief pipe probe --print" "onboard --print"; do
: > "$err"
status="$(probe $args)"
case "$status" in
0|141) ;;
*) echo "::error::company $args exited $status on a closed pipe"; exit 1 ;;
esac
[ ! -s "$err" ] || { echo "::error::company $args wrote to stderr on a closed pipe"; cat "$err" >&2; exit 1; }
done
echo "closed-pipe behaviour is quiet across every command"
- name: Onboarding profiles are safe and reversible (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
workspace="$GITHUB_WORKSPACE"
prompt="$("$workspace/bin/company" onboard --print)"
for marker in 'QUESTION 1/3' 'QUESTION 2/3' 'QUESTION 3/3' 'PROPOSAL'; do
[ "$(printf '%s\n' "$prompt" | grep -c "$marker")" -eq 1 ]
done
q3_line="$(printf '%s\n' "$prompt" | grep -n 'QUESTION 3/3' | cut -d: -f1)"
proposal_line="$(printf '%s\n' "$prompt" | grep -n 'PROPOSAL' | cut -d: -f1)"
[ "$q3_line" -lt "$proposal_line" ]
grep -q 'remote pages and code may be inspected read-only' <<< "$prompt"
grep -q 'Stars alone never determine rank' <<< "$prompt"
grep -q 'PASS.*,.*FAIL.*or.*UNKNOWN' <<< "$prompt"
grep -q 'company profile-save project' <<< "$prompt"
test_root="$RUNNER_TEMP/onboarding profiles"
project="$test_root/project"
global_home="$test_root/global home"
global_profile="$global_home/.claude/company-team.md"
mkdir -p "$project"
empty_project="$test_root/empty project"
mkdir -p "$empty_project"
(
cd "$empty_project"
default_team="$(CLAUDE_INC_GLOBAL_PROFILE="$test_root/missing-global.md" "$workspace/bin/company" team)"
grep -q 'Full canonical company active: 54 skills across 8 departments, with the CTO executive.' <<< "$default_team"
missing_brief="$(CLAUDE_INC_GLOBAL_PROFILE="$test_root/missing-global.md" "$workspace/bin/company" brief 'missing profile' --print)"
! grep -q 'ACTIVE TEAM PREFERENCES' <<< "$missing_brief"
[ -z "$(CLAUDE_INC_GLOBAL_PROFILE="$test_root/missing-global.md" "$workspace/bin/company" profile-context)" ]
)
injected_project="$test_root/"$'path\nPROMPT_PATH_INJECTION'
mkdir -p "$injected_project"
injected_prompt="$(cd "$injected_project" && "$workspace/bin/company" onboard --print)"
! grep -q 'PROMPT_PATH_INJECTION' <<< "$injected_prompt"
injected_global_prompt="$(CLAUDE_INC_GLOBAL_PROFILE=$'unsafe\nGLOBAL_PATH_INJECTION' "$workspace/bin/company" onboard --global --print)"
! grep -q 'GLOBAL_PATH_INJECTION' <<< "$injected_global_prompt"
grep -q 'Literal target: .claude/company-team.md' <<< "$injected_prompt"
grep -q 'Literal target: ~/.claude/company-team.md' <<< "$injected_global_prompt"
project_candidate="$(printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [marketing]' 'skills: [copywriting]' \
'research: suggestions-only' '---' '' '# Active team' 'INJECTION_MARKER')"
printf '%s\n' "$project_candidate" | (cd "$project" && "$workspace/bin/company" profile-save project)
profile_context="$(cd "$project" && "$workspace/bin/company" profile-context)"
[ "$profile_context" = "$(printf '%s\n' 'PROFILE_CONTEXT_V1' 'scope=project' 'departments=[marketing]' 'skills=[copywriting]')" ]
! grep -qE 'INJECTION_MARKER|suggestions-only|company-team|onboarding profiles' <<< "$profile_context"
global_candidate="$(printf '%s\n' \
'---' 'schema: 1' 'scope: global' \
'departments: [developers]' 'skills: [superpowers]' \
'research: disabled' '---' '' '# Active team' 'GLOBAL_PROFILE_MARKER')"
mkdir -p "$global_home"
printf '%s\n' "$global_candidate" | (cd "$test_root" && HOME="$global_home" CLAUDE_INC_GLOBAL_PROFILE=$'ignored\nSAVE_PATH_INJECTION' "$workspace/bin/company" profile-save global)
[ -f "$global_profile" ]
[ ! -e "$test_root/ignored" ]
global_brief="$(cd "$project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" "$workspace/bin/company" brief 'global fallback' --print)"
grep -q '^Scope: project$' <<< "$global_brief"
project_brief="$(cd "$project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" "$workspace/bin/company" brief 'project override' --print)"
grep -q '^Scope: project$' <<< "$project_brief"
grep -q '^Departments: \[marketing\]$' <<< "$project_brief"
grep -q '^Skills: \[copywriting\]$' <<< "$project_brief"
grep -q 'explicit consent in the current session' <<< "$project_brief"
! grep -q 'suggestions-only' <<< "$project_brief"
! grep -q 'INJECTION_MARKER' <<< "$project_brief"
! grep -q 'GLOBAL_PROFILE_MARKER' <<< "$project_brief"
team_output="$(cd "$project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" "$workspace/bin/company" team)"
grep -q '^Skills: \[copywriting\]$' <<< "$team_output"
grep -q '^Research metadata (does not grant consent): suggestions-only$' <<< "$team_output"
! grep -q 'INJECTION_MARKER' <<< "$team_output"
! grep -qE 'company-team|onboarding profiles' <<< "$team_output"
global_project="$test_root/global project"
mkdir -p "$global_project"
global_brief="$(cd "$global_project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" "$workspace/bin/company" brief 'global fallback' --print)"
grep -q '^Scope: global$' <<< "$global_brief"
grep -q '^Departments: \[developers\]$' <<< "$global_brief"
! grep -q 'GLOBAL_PROFILE_MARKER' <<< "$global_brief"
symlink_project="$test_root/symlink project"
symlink_target="$test_root/symlink target.md"
mkdir -p "$symlink_project/.claude"
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [superpowers]' \
'research: disabled' '---' 'SYMLINK_BODY_MUST_NOT_LEAK' > "$symlink_target"
ln -s "$symlink_target" "$symlink_project/.claude/company-team.md"
if (cd "$symlink_project" && CLAUDE_INC_GLOBAL_PROFILE="$test_root/missing-global.md" \
"$workspace/bin/company" brief 'symlink profile' --print > "$test_root/symlink.out" 2> "$test_root/symlink.err"); then
echo 'symlink profile unexpectedly accepted' >&2
exit 1
fi
grep -q 'symbolic links are not allowed' "$test_root/symlink.err"
! grep -q 'SYMLINK_BODY_MUST_NOT_LEAK' "$test_root/symlink.out"
! grep -Fq "$symlink_project" "$test_root/symlink.err"
check_invalid() {
expected="$1"
output_file="$test_root/$expected.out"
error_file="$test_root/$expected.err"
if (cd "$project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" \
"$workspace/bin/company" brief 'invalid profile' --print > "$output_file" 2> "$error_file"); then
echo "$expected unexpectedly accepted" >&2
return 1
fi
grep -q 'company: invalid project team profile:' "$error_file"
! grep -Fq "$project" "$error_file"
! grep -q 'INVALID_PROFILE_BODY\|GLOBAL_PROFILE_MARKER' "$output_file"
! grep -q 'ACTIVE TEAM PREFERENCES' "$output_file"
}
mkdir -p "$workspace/skills/evil"
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [evil]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid evil-local-directory
rmdir "$workspace/skills/evil"
printf '%s\n' 'not frontmatter' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid malformed
printf '%s\n' \
'---' 'schema: 1' 'scope: global' \
'departments: [developers]' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid wrong-scope
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [unknown-team]' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid unknown-department
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [unknown-skill]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid unknown-skill
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
head -c 33000 /dev/zero | tr '\0' x >> "$project/.claude/company-team.md"
check_invalid oversized
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
printf '\0' >> "$project/.claude/company-team.md"
check_invalid nul-under-limit
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers, developers]' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid duplicate-department
printf '%s\n' \
'---' 'schema: 1' 'departments: [developers]' \
'scope: project' 'skills: [superpowers]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid reordered-frontmatter
printf '%s\n' \
'---' 'schema: 1' 'scope: project' \
'departments: [developers]' 'skills: [copywriting]' \
'research: disabled' '---' 'INVALID_PROFILE_BODY' > "$project/.claude/company-team.md"
check_invalid mismatched-skill-department
invalid_project_error="$test_root/invalid-project-no-fallback.err"
if (cd "$project" && CLAUDE_INC_GLOBAL_PROFILE="$global_profile" "$workspace/bin/company" profile-context > /dev/null 2> "$invalid_project_error"); then
echo 'invalid-project-no-fallback unexpectedly succeeded' >&2
exit 1
fi
grep -q 'invalid project team profile' "$invalid_project_error"
! grep -Fq "$project" "$invalid_project_error"
exact_project="$test_root/exact-32768"
mkdir -p "$exact_project"
exact_prefix="$(printf '%s\n' '---' 'schema: 1' 'scope: project' 'departments: [developers]' 'skills: [superpowers]' 'research: disabled' '---')"
exact_prefix="$exact_prefix"$'\n'
exact_padding=$((32768 - ${#exact_prefix}))
{ printf '%s' "$exact_prefix"; head -c "$exact_padding" /dev/zero | tr '\0' x; } | (cd "$exact_project" && "$workspace/bin/company" profile-save project)
[ "$(wc -c < "$exact_project/.claude/company-team.md" | tr -d '[:space:]')" -eq 32768 ]
nul_project="$test_root/nul-under-limit"
mkdir -p "$nul_project"
if { printf '%s\n' '---' 'schema: 1' 'scope: project' 'departments: [developers]' 'skills: [superpowers]' 'research: disabled' '---'; printf '\0'; } | (cd "$nul_project" && "$workspace/bin/company" profile-save project); then
echo 'nul-under-limit unexpectedly saved' >&2
exit 1
fi
[ ! -e "$nul_project/.claude/company-team.md" ]
save_rejects() {
name="$1"
candidate="$2"
save_project="$test_root/$name"
mkdir -p "$save_project"
if printf '%s\n' "$candidate" | (cd "$save_project" && "$workspace/bin/company" profile-save project); then
echo "$name unexpectedly saved" >&2
return 1
fi
[ ! -e "$save_project/.claude/company-team.md" ]
}
save_rejects duplicate-skill "$(printf '%s\n' '---' 'schema: 1' 'scope: project' 'departments: [developers]' 'skills: [superpowers, superpowers]' 'research: disabled' '---')"
save_rejects reordered-save "$(printf '%s\n' '---' 'scope: project' 'schema: 1' 'departments: [developers]' 'skills: [superpowers]' 'research: disabled' '---')"
symlink_save="$test_root/symlink-target"
mkdir -p "$symlink_save/.claude"
ln -s "$test_root/symlink target.md" "$symlink_save/.claude/company-team.md"
if printf '%s\n' "$project_candidate" | (cd "$symlink_save" && "$workspace/bin/company" profile-save project); then exit 1; fi
symlink_parent="$test_root/symlink-parent"
mkdir -p "$symlink_parent" "$test_root/real profile parent"
ln -s "$test_root/real profile parent" "$symlink_parent/.claude"
if printf '%s\n' "$project_candidate" | (cd "$symlink_parent" && "$workspace/bin/company" profile-save project); then exit 1; fi
special_project="$test_root/special-target"
mkdir -p "$special_project/.claude"
mkfifo "$special_project/.claude/company-team.md"
if printf '%s\n' "$project_candidate" | (cd "$special_project" && "$workspace/bin/company" profile-save project); then exit 1; fi
replace_project="$test_root/replace-confirmed"
mkdir -p "$replace_project"
printf '%s\n' "$project_candidate" | (cd "$replace_project" && "$workspace/bin/company" profile-save project)
if printf '%s\n' "$global_candidate" | (cd "$replace_project" && "$workspace/bin/company" profile-save project); then exit 1; fi
grep -q 'scope: project' "$replace_project/.claude/company-team.md"
replacement="$(printf '%s\n' '---' 'schema: 1' 'scope: project' 'departments: [developers]' 'skills: [superpowers]' 'research: disabled' '---' 'REPLACED')"
printf '%s\n' "$replacement" | (cd "$replace_project" && "$workspace/bin/company" profile-save project --replace)
grep -q 'REPLACED' "$replace_project/.claude/company-team.md"
deferred="$(cd "$project" && CLAUDE_INC_ENGINE=missing-company-engine "$workspace/bin/company" onboard < /dev/null)"
[ "$deferred" = 'Onboarding deferred. Run: company onboard' ]
- name: The CLI can brief every department (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$departments = @('developers', 'designers', 'marketing', 'social-media', 'finance', 'small-business', 'legal', 'sales')
foreach ($department in $departments) {
$output = & bash ./bin/company $department 'ci smoke test' --print
if ($LASTEXITCODE -ne 0) { throw "CLI failed for $department" }
$count = @($output | Select-String '^----- EMPLOYEE:').Count
Write-Host "$department -> $count employees"
if ($count -ne 6) { throw "$department composed $count employees, expected 6" }
}
$brief = & bash ./bin/company brief 'ci smoke test' --print
if ($LASTEXITCODE -ne 0) { throw 'CLI brief failed' }
if (-not ($brief | Select-String 'CEO Operating Manual')) { throw 'CEO Operating Manual missing from CLI brief' }
& bash ./bin/company roster | Out-Null
if ($LASTEXITCODE -ne 0) { throw 'CLI roster failed' }
$version = & bash ./bin/company version
if ($LASTEXITCODE -ne 0 -or $version -ne 'company v1.5.0') { throw "Unexpected CLI version: $version" }
$prompt = (& bash ./bin/company onboard --print) -join "`n"
foreach ($marker in @('QUESTION 1/3', 'QUESTION 2/3', 'QUESTION 3/3', 'PROPOSAL')) {
if ([regex]::Matches($prompt, [regex]::Escape($marker)).Count -ne 1) { throw "Unexpected onboarding marker count: $marker" }
}
if (-not $prompt.Contains('remote pages and code may be inspected read-only')) { throw 'Research inspection boundary missing' }
if (-not $prompt.Contains('Stars alone never determine rank')) { throw 'Research quality gate missing' }
if (-not $prompt.Contains('company profile-save project')) { throw 'Profile save helper missing from onboarding prompt' }
$company = (Resolve-Path './bin/company').Path
$testRoot = Join-Path $env:RUNNER_TEMP 'profile smoke with spaces'
$project = Join-Path $testRoot 'project with spaces'
$globalProject = Join-Path $testRoot 'global project with spaces'
$globalHome = Join-Path $testRoot 'global home'
$globalProfile = Join-Path $globalHome '.claude/company-team.md'
New-Item -ItemType Directory -Force -Path (Join-Path $project '.claude'), $globalProject, $globalHome | Out-Null
function Write-TeamProfile([string]$Path, [string]$Scope, [string]$Departments, [string]$Skills, [string]$Body, [string]$Research = 'disabled') {
$content = @('---', 'schema: 1', "scope: $Scope", "departments: $Departments", "skills: $Skills", "research: $Research", '---', '', $Body) -join "`n"
[IO.File]::WriteAllText($Path, $content, [Text.UTF8Encoding]::new($false))
}
$globalCandidate = Join-Path $testRoot 'global candidate.md'
Write-TeamProfile $globalCandidate 'global' '[developers]' '[superpowers]' 'WINDOWS_GLOBAL_BODY'
$env:HOME = $globalHome
$env:CLAUDE_INC_GLOBAL_PROFILE = $globalProfile
& bash -l -c '"$1" profile-save global < "$2"' bash $company $globalCandidate
if ($LASTEXITCODE -ne 0) { throw 'Windows global profile-save failed' }
Push-Location $globalProject
try { $globalBrief = (& bash -l $company brief 'global fallback' --print) -join "`n" } finally { Pop-Location }
if (-not $globalBrief.Contains('Scope: global') -or -not $globalBrief.Contains('Skills: [superpowers]')) { throw 'Windows global fallback failed' }
if ($globalBrief.Contains('WINDOWS_GLOBAL_BODY')) { throw 'Windows global body leaked' }
$projectProfile = Join-Path $project '.claude/company-team.md'
$projectCandidate = Join-Path $testRoot 'project candidate.md'
Write-TeamProfile $projectCandidate 'project' '[marketing]' '[copywriting]' 'INJECTION_MARKER' 'suggestions-only'
Push-Location $project
try {
& bash -l -c '"$1" profile-save project < "$2"' bash $company $projectCandidate
if ($LASTEXITCODE -ne 0) { throw 'Windows project profile-save failed' }
$projectBrief = (& bash -l $company brief 'project override' --print) -join "`n"
$teamOutput = (& bash -l $company team) -join "`n"
$profileContext = (& bash -l $company profile-context) -join "`n"
} finally { Pop-Location }
if (-not $projectBrief.Contains('Scope: project') -or -not $projectBrief.Contains('Skills: [copywriting]')) { throw 'Windows project profile failed' }
if (-not $projectBrief.Contains('explicit consent in the current session') -or $projectBrief.Contains('suggestions-only')) { throw 'Stored research metadata granted or implied consent' }
if (-not $teamOutput.Contains('Research metadata (does not grant consent): suggestions-only')) { throw 'Windows team metadata display failed' }
if ($projectBrief.Contains('INJECTION_MARKER') -or $teamOutput.Contains('INJECTION_MARKER')) { throw 'Windows profile body leaked' }
if ($projectBrief.Contains('WINDOWS_GLOBAL_BODY')) { throw 'Windows project did not override global' }
if ($profileContext -ne "PROFILE_CONTEXT_V1`nscope=project`ndepartments=[marketing]`nskills=[copywriting]") { throw "Windows profile-context mismatch: $profileContext" }
if ($profileContext.Contains('INJECTION_MARKER') -or $profileContext.Contains('suggestions-only') -or $profileContext.Contains('company-team')) { throw 'Windows profile-context leaked profile data' }
if ($teamOutput.Contains($project) -or $teamOutput.Contains('company-team')) { throw 'Windows team output leaked a profile path' }
$crlfContent = @('---','schema: 1','scope: project','departments: [developers]','skills: [superpowers]','research: disabled','---','CRLF_BODY') -join "`r`n"
[IO.File]::WriteAllText($projectProfile, $crlfContent, [Text.UTF8Encoding]::new($false))
Push-Location $project
try { $crlfBrief = (& bash -l $company brief 'crlf profile' --print) -join "`n" } finally { Pop-Location }
if (-not $crlfBrief.Contains('Scope: project') -or -not $crlfBrief.Contains('Skills: [superpowers]')) { throw 'Windows CRLF profile failed' }
if ($crlfBrief.Contains('CRLF_BODY')) { throw 'Windows CRLF body leaked' }
$env:CLAUDE_INC_GLOBAL_PROFILE = Join-Path $testRoot 'missing global profile.md'
$invalidCases = @(
[pscustomobject]@{ Name = 'malformed'; Content = "not frontmatter`nINVALID_BODY" },
[pscustomobject]@{ Name = 'unknown-department'; Content = (@('---','schema: 1','scope: project','departments: [evil]','skills: [superpowers]','research: disabled','---','INVALID_BODY') -join "`n") },
[pscustomobject]@{ Name = 'unknown-skill'; Content = (@('---','schema: 1','scope: project','departments: [developers]','skills: [evil]','research: disabled','---','INVALID_BODY') -join "`n") },
[pscustomobject]@{ Name = 'duplicate-department'; Content = (@('---','schema: 1','scope: project','departments: [developers, developers]','skills: [superpowers]','research: disabled','---','INVALID_BODY') -join "`n") },
[pscustomobject]@{ Name = 'reordered-frontmatter'; Content = (@('---','scope: project','schema: 1','departments: [developers]','skills: [superpowers]','research: disabled','---','INVALID_BODY') -join "`n") },
[pscustomobject]@{ Name = 'oversized'; Content = ((@('---','schema: 1','scope: project','departments: [developers]','skills: [superpowers]','research: disabled','---','INVALID_BODY') -join "`n") + ('x' * 33000)) }
)
foreach ($case in $invalidCases) {
[IO.File]::WriteAllText($projectProfile, $case.Content, [Text.UTF8Encoding]::new($false))
Push-Location $project
try {
$invalidOutput = (& bash -l $company brief $case.Name --print 2>&1) -join "`n"
$invalidExit = $LASTEXITCODE
} finally { Pop-Location }
if ($invalidExit -eq 0) { throw "Windows invalid profile was accepted: $($case.Name)" }
if (-not $invalidOutput.Contains('invalid project team profile')) { throw "Windows invalid profile was not warned: $($case.Name)" }
if ($invalidOutput.Contains('INVALID_BODY') -or $invalidOutput.Contains('ACTIVE TEAM PREFERENCES')) { throw "Windows invalid profile leaked: $($case.Name)" }
if ($invalidOutput.Contains($project)) { throw "Windows invalid profile leaked its path: $($case.Name)" }
}
# invalid-project-no-fallback
Write-TeamProfile $projectProfile 'project' '[developers]' '[copywriting]' 'INVALID_PROFILE_BODY'
Push-Location $project
try {
$invalidFallback = (& bash -l $company profile-context 2>&1) -join "`n"
$invalidFallbackExit = $LASTEXITCODE
} finally { Pop-Location }
if ($invalidFallbackExit -eq 0 -or -not $invalidFallback.Contains('invalid project team profile')) { throw 'Windows invalid project profile did not fail closed' }
if ($invalidFallback.Contains('WINDOWS_GLOBAL_BODY') -or $invalidFallback.Contains($project)) { throw 'Windows invalid project profile leaked or fell back' }
# exact-32768
$exactProject = Join-Path $testRoot 'exact-32768'
$exactCandidate = Join-Path $testRoot 'exact-32768.md'
New-Item -ItemType Directory -Force -Path $exactProject | Out-Null
$exactPrefix = (@('---','schema: 1','scope: project','departments: [developers]','skills: [superpowers]','research: disabled','---') -join "`n") + "`n"
$exactBytes = [Text.Encoding]::UTF8.GetBytes($exactPrefix)
$exactContent = New-Object byte[] 32768
[Array]::Copy($exactBytes, $exactContent, $exactBytes.Length)
for ($index = $exactBytes.Length; $index -lt 32768; $index++) { $exactContent[$index] = [byte][char]'x' }
[IO.File]::WriteAllBytes($exactCandidate, $exactContent)
Push-Location $exactProject
try { & bash -l -c '"$1" profile-save project < "$2"' bash $company $exactCandidate; $exactExit = $LASTEXITCODE } finally { Pop-Location }
if ($exactExit -ne 0 -or (Get-Item (Join-Path $exactProject '.claude/company-team.md')).Length -ne 32768) { throw 'Windows exact-32768 profile failed' }
# nul-under-limit
$nulProject = Join-Path $testRoot 'nul-under-limit'
$nulCandidate = Join-Path $testRoot 'nul-under-limit.md'
New-Item -ItemType Directory -Force -Path $nulProject | Out-Null
[byte[]]$nulBytes = [Text.Encoding]::UTF8.GetBytes($exactPrefix + 'body') + [byte]0
[IO.File]::WriteAllBytes($nulCandidate, $nulBytes)
Push-Location $nulProject
try { & bash -l -c '"$1" profile-save project < "$2"' bash $company $nulCandidate; $nulExit = $LASTEXITCODE } finally { Pop-Location }
if ($nulExit -eq 0 -or (Test-Path -LiteralPath (Join-Path $nulProject '.claude/company-team.md'))) { throw 'Windows nul-under-limit profile was accepted' }
# replace-confirmed
$replaceCandidate = Join-Path $testRoot 'replace candidate.md'
Write-TeamProfile $replaceCandidate 'project' '[developers]' '[superpowers]' 'REPLACED'
Push-Location $project
try {
& bash -l -c '"$1" profile-save project < "$2"' bash $company $replaceCandidate
$replaceRefused = $LASTEXITCODE
& bash -l -c '"$1" profile-save project --replace < "$2"' bash $company $replaceCandidate
$replaceAccepted = $LASTEXITCODE
} finally { Pop-Location }
if ($replaceRefused -eq 0 -or $replaceAccepted -ne 0) { throw 'Windows replacement confirmation contract failed' }
if (-not ([IO.File]::ReadAllText($projectProfile).Contains('REPLACED'))) { throw 'Windows confirmed replacement did not persist' }
- name: Global, project and no-CLI installs work (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: |
workspace="$GITHUB_WORKSPACE"
test_root="$RUNNER_TEMP/install smoke"
export HOME="$test_root/global home"
mkdir -p "$HOME"
bash "$workspace/install.sh"
bash "$workspace/install.sh"
[ "$(ls -1 "$HOME/.claude/skills" | wc -l | tr -d ' ')" -eq 54 ]
[ "$(ls -1 "$HOME/.claude/agents" | wc -l | tr -d ' ')" -eq 9 ]
[ -L "$HOME/.local/bin/company" ]
[ "$("$HOME/.local/bin/company" version)" = "company v1.5.0" ]
export HOME="$test_root/project home"
project="$test_root/project with spaces"
mkdir -p "$HOME" "$project"
(cd "$project" && bash "$workspace/install.sh" --project)
[ "$(ls -1 "$project/.claude/skills" | wc -l | tr -d ' ')" -eq 54 ]
[ "$(ls -1 "$project/.claude/agents" | wc -l | tr -d ' ')" -eq 9 ]
export HOME="$test_root/no cli home"
mkdir -p "$HOME"
bash "$workspace/install.sh" --no-bin
[ ! -e "$HOME/.local/bin/company" ]
export HOME="$test_root/onboard home"
onboard_project="$test_root/onboard project"
mkdir -p "$HOME" "$onboard_project"
onboard_output="$(cd "$onboard_project" && CLAUDE_INC_ENGINE=missing-company-engine bash "$workspace/install.sh" --project --no-bin --onboard)"
grep -q '^Onboarding deferred. Install the Claude Code plugin, then run: /claude-inc:onboard$' <<< "$onboard_output"
! grep -q 'Run: company onboard' <<< "$onboard_output"
[ ! -e "$onboard_project/.claude/company-team.md" ]
- name: Piped project install clones the checked-out commit (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: |
workspace="$GITHUB_WORKSPACE"
test_root="$(mktemp -d "$RUNNER_TEMP/claude-inc-piped.XXXXXX")"
project="$test_root/project"
mkdir -p "$project"
(
cd "$project"
export CLAUDE_INC_HOME="$test_root/cache"
export CLAUDE_INC_REPO_URL="file://$workspace"
cat "$workspace/install.sh" | bash -s -- --project --no-bin > "$test_root/install.out"
)
! grep -q 'QUESTION [123]/3' "$test_root/install.out"
[ ! -e "$project/.claude/company-team.md" ]
expected_commit="$(git -C "$workspace" rev-parse HEAD)"
checkout_count=0
promoted_checkout=""
for checkout in "$test_root/cache.checkouts"/*; do
[ -d "$checkout" ] || continue
checkout_count=$((checkout_count + 1))
promoted_checkout="$checkout"
done
[ "$checkout_count" -eq 1 ]
[ "${promoted_checkout##*/}" = "$expected_commit" ]
[ "$(git -C "$promoted_checkout" rev-parse HEAD)" = "$expected_commit" ]
[ -z "$(git -C "$promoted_checkout" status --porcelain --untracked-files=all)" ]
! find "$test_root" -maxdepth 1 -name 'cache.candidate.*' -print -quit | grep -q .
[ -f "$project/.claude/commands/company.md" ]
cmp -s "$workspace/commands/company.md" "$project/.claude/commands/company.md"
skill_count=0
for skill in "$project/.claude/skills"/*/; do
[ -d "$skill" ] || continue
skill_count=$((skill_count + 1))
done
agent_count=0
for agent in "$project/.claude/agents"/*.md; do
[ -f "$agent" ] || continue
agent_count=$((agent_count + 1))
done
[ "$skill_count" -eq 54 ]
[ "$agent_count" -eq 9 ]
- name: Global, project and no-CLI installs work (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$workspace = $env:GITHUB_WORKSPACE
$testRoot = Join-Path $env:RUNNER_TEMP 'install smoke'
$env:HOME = Join-Path $testRoot 'global home'
New-Item -ItemType Directory -Force -Path $env:HOME | Out-Null
& "$workspace/install.ps1"
& "$workspace/install.ps1"
if ((Get-ChildItem "$env:HOME/.claude/skills" -Directory).Count -ne 54) { throw 'Global skill count is not 54' }
if ((Get-ChildItem "$env:HOME/.claude/agents" -File).Count -ne 9) { throw 'Global agent count is not 9' }
$wrapper = Join-Path $env:HOME '.local/bin/company.exe'
if (-not (Test-Path -LiteralPath $wrapper)) { throw 'CLI wrapper was not installed' }
$version = & $wrapper version
if ($LASTEXITCODE -ne 0 -or $version -ne 'company v1.5.0') { throw "Unexpected installed CLI version: $version" }
$wrapperProject = Join-Path $testRoot 'wrapper profile project with spaces'
$wrapperProfileDir = Join-Path $wrapperProject '.claude'
New-Item -ItemType Directory -Force -Path $wrapperProfileDir | Out-Null
$wrapperProfile = Join-Path $wrapperProfileDir 'company-team.md'
$wrapperContent = @('---','schema: 1','scope: project','departments: [developers]','skills: [superpowers]','research: disabled','---','WRAPPER_INJECTION_MARKER') -join "`n"
[IO.File]::WriteAllText($wrapperProfile, $wrapperContent, [Text.UTF8Encoding]::new($false))
Push-Location $wrapperProject
try { $wrapperBrief = (& $wrapper brief 'wrapper profile' --print) -join "`n" } finally { Pop-Location }
if (-not $wrapperBrief.Contains('Scope: project') -or -not $wrapperBrief.Contains('Skills: [superpowers]')) { throw 'Windows wrapper profile failed' }
if ($wrapperBrief.Contains('WRAPPER_INJECTION_MARKER')) { throw 'Windows wrapper leaked profile body' }
$env:HOME = Join-Path $testRoot 'project home'
$project = Join-Path $testRoot 'project with spaces'
New-Item -ItemType Directory -Force -Path $env:HOME, $project | Out-Null
Push-Location $project
try { & "$workspace/install.ps1" -Project } finally { Pop-Location }
if ((Get-ChildItem "$project/.claude/skills" -Directory).Count -ne 54) { throw 'Project skill count is not 54' }
if ((Get-ChildItem "$project/.claude/agents" -File).Count -ne 9) { throw 'Project agent count is not 9' }
$env:HOME = Join-Path $testRoot 'no cli home'
New-Item -ItemType Directory -Force -Path $env:HOME | Out-Null
& "$workspace/install.ps1" -NoBin
if (Test-Path -LiteralPath "$env:HOME/.local/bin/company.exe") { throw 'NoBin installed a CLI wrapper' }
$env:HOME = Join-Path $testRoot 'onboard home'
$env:CLAUDE_INC_ENGINE = 'missing-company-engine'
$onboardProject = Join-Path $testRoot 'onboard project'
New-Item -ItemType Directory -Force -Path $env:HOME, $onboardProject | Out-Null
Push-Location $onboardProject
try { $onboardOutput = & "$workspace/install.ps1" -Project -NoBin -Onboard | Out-String } finally { Pop-Location }
if (-not $onboardOutput.Contains('Onboarding deferred.')) { throw 'Project onboarding did not defer safely' }
if ($onboardOutput.Contains('Run: company onboard')) { throw 'NoBin advised an unavailable company command' }
if (-not $onboardOutput.Contains('Install the Claude Code plugin, then run: /claude-inc:onboard')) { throw 'NoBin deferred guidance is not actionable' }
if (Test-Path -LiteralPath (Join-Path $onboardProject '.claude/company-team.md')) { throw 'Deferred onboarding created a profile' }
- name: Real installed company project lifecycle (macOS and Linux)
if: runner.os != 'Windows'
run: python3 tests/project_install_smoke.py
- name: Real installed company.exe project lifecycle (Windows)
if: runner.os == 'Windows'
run: python tests/project_install_smoke.py --quote-probe
- name: Native launcher literal arguments and process contract (Windows)
if: runner.os == 'Windows'
run: python -m unittest discover -s tests -p test_windows_launcher.py
- name: Canonical company examples preserve fenced Markdown
run: python -m unittest discover -s tests -p test_company_builder.py
- name: Installer collisions fail without mutation (macOS and Linux)
if: runner.os != 'Windows'
shell: bash
run: bash tests/installers_safety.sh
- name: Installer collisions fail without mutation (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: ./tests/installers_safety.ps1