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
6 changes: 6 additions & 0 deletions .github/workflows/ci-rerun.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# CI Rerun — Manual workflow for re-running CI on fork PRs or PRs that need
# a fresh CI pass without push. Useful when:
# - Fork PRs don't trigger CI automatically (security restriction)
# - A PR needs re-testing after an infrastructure flake
# - You need to validate a PR against current base branch state
# Usage: Actions → CI Rerun (Manual) → enter PR number → Run workflow
name: CI Rerun (Manual)

on:
Expand Down
74 changes: 71 additions & 3 deletions .github/workflows/squad-npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,70 @@ permissions:
contents: read
id-token: write
jobs:
preflight:
name: Pre-publish dependency validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "Scan for file: references in package.json files"
run: |
echo "Scanning all packages/*/package.json for file: references..."
FOUND=0
for pkg in packages/*/package.json; do
# Check dependencies, devDependencies, and optionalDependencies for file: refs
MATCHES=$(node -e "
const pkg = require('./$pkg');
const sections = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'];
for (const s of sections) {
for (const [name, ver] of Object.entries(pkg[s] || {})) {
if (String(ver).startsWith('file:')) {
console.log(' ❌ ' + s + '.' + name + ' = ' + ver);
}
}
}
")
if [ -n "$MATCHES" ]; then
echo "::error::file: dependency found in $pkg"
echo "$pkg:"
echo "$MATCHES"
FOUND=1
fi
done
if [ "$FOUND" -eq 1 ]; then
echo ""
echo "::error::PUBLISH BLOCKED — file: references break global installs (see v0.9.1 incident)"
echo "Fix: Replace file: references with proper version ranges before publishing."
exit 1
fi
echo "✅ No file: references found — safe to publish"
- name: Validate semver versions
run: |
echo "Validating version numbers are valid semver..."
node -e "
const fs = require('fs');
const path = require('path');
const semverRe = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/;
const pkgs = fs.readdirSync('packages', { withFileTypes: true })
.filter(d => d.isDirectory())
.map(d => path.join('packages', d.name, 'package.json'))
.filter(p => fs.existsSync(p));
let failed = false;
for (const p of pkgs) {
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
if (!semverRe.test(pkg.version)) {
console.error('::error::Invalid semver in ' + p + ': ' + pkg.version);
failed = true;
} else {
console.log('✅ ' + pkg.name + '@' + pkg.version);
}
}
if (failed) process.exit(1);
"
smoke-test:
name: CLI packaging smoke test
needs: preflight
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -28,11 +90,17 @@ jobs:
run: npm run build
env:
SKIP_BUILD_BUMP: '1'
- name: Validate npm pack succeeds
run: |
echo "Verifying npm pack produces valid tarballs..."
npm -w packages/squad-sdk pack --dry-run
npm -w packages/squad-cli pack --dry-run
echo "✅ Both packages pack successfully"
- name: Run CLI smoke tests
run: npx vitest run test/cli-packaging-smoke.test.ts
publish-sdk:
name: Publish @bradygaster/squad-sdk
needs: smoke-test
needs: [preflight, smoke-test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -82,7 +150,7 @@ jobs:
echo "Registry propagation slow but package was published successfully"
publish-cli:
name: Publish @bradygaster/squad-cli
needs: [smoke-test, publish-sdk]
needs: [preflight, smoke-test, publish-sdk]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -105,7 +173,7 @@ jobs:
echo "Publishing version: ${VERSION}"
- name: Install dependencies
run: npm ci
- name: Guard against file: dependencies
- name: "Guard against file: dependencies"
run: |
SDK_DEP=$(node -p "require('./packages/squad-cli/package.json').dependencies['@bradygaster/squad-sdk']")
if [[ "$SDK_DEP" == file:* ]]; then
Expand Down
6 changes: 4 additions & 2 deletions .squad/agents/booster/charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

## How I Work

**NEVER:** Publish without semver validation; npm publish without NPM_TOKEN type check; verify steps without retry logic; workflows committing to main/dev; skip branch verification.
**NEVER:** Publish without semver validation; npm publish without NPM_TOKEN type check; verify steps without retry logic; workflows committing to main/dev; skip branch verification; publish with `file:` or `link:` references in package.json.

**ALWAYS:** Semver validation before publish; NPM_TOKEN type = Automation; retry logic for external services; structured logging; remediation steps in errors; branch validation; require PRs for protected branches; verify PR→issue references; scan for secrets; CI check for stale assertions.
**ALWAYS:** Semver validation before publish; NPM_TOKEN type = Automation; retry logic for external services; structured logging; remediation steps in errors; branch validation; require PRs for protected branches; verify PR→issue references; scan for secrets; CI check for stale assertions; preflight dependency scan before any publish job; `npm pack --dry-run` validation in smoke tests.

**RELEASE SKILL:** Read `.squad/skills/release-process/SKILL.md` before any publish pipeline work. It contains battle-tested rules from the v0.9.1 incident.

## Boundaries

Expand Down
46 changes: 46 additions & 0 deletions .squad/agents/booster/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,49 @@ Analyzed 20 CI runs from March 15. Identified 3 distinct failure categories:
3. TypeScript workspace reference health check (catch SDK/CLI type mismatches early)
4. Better failure grouping/attribution in CI UI (distinguish "new gate" vs "regression")
5. Spell check dictionary maintenance workflow (easier to add known-good usernames/terms)

### CI Workflow Audit — March 23, 2026

**Status:** Conducted full audit of 15 workflow files. Brady's perception ("complete nightmare, 12,000 workflows") is not accurate — the codebase is lean, well-organized, and 99% authored by Brady (bradygaster + Copilot).

**Key Findings:**
- **Total workflows:** 15 (7 load-bearing core, 7 admin/automation, 1 ghost)
- **Authorship:** bradygaster 46 commits (65%), Copilot 7 (10%), team 17 (24%)
- **v0.9.1 Scramble:** Copilot made 4 commits on 2026-03-23 trying to work around GitHub platform bug (workflow_dispatch returns 422 after file renames/deletes)
- **Ghost file identified:** `publish-npm.yml` (deleted but still in GitHub's workflow cache) → requires manual deletion via API
- **Zero duplication:** Each workflow has clear, non-overlapping responsibility
- **One optional cleanup:** `ci-rerun.yml` (useful but not essential)

**Release Pipeline Quality:**
- Core pipeline (squad-ci → squad-release → squad-npm-publish → insider-*) is solid
- Smoke tests run before any npm publish (good safety gate)
- Implicit ordering works but fragile (squad-npm-publish depends on release: published event)

**Triage Automation Quality:**
- Label routing (squad-triage, squad-issue-assign, squad-label-enforce) well-integrated
- Ralph heartbeat has cron disabled (event-driven only)
- Works correctly with @copilot assignment

**Recommendation:** Delete ghost publish-npm.yml file, optionally keep ci-rerun for fork PR debugging, keep everything else. CI health is good.

**Report written to:** `.squad/decisions/inbox/booster-ci-audit.md`

### CI Cleanup & Hardening — Post-Audit

**Changes shipped:**

1. **Ghost workflow disabled** — `publish-npm.yml` (workflow ID 250121956) disabled via GitHub API (`PUT /actions/workflows/{id}/disable`). GitHub doesn't support DELETE on workflow entries; disable is the permanent fix.

2. **Pre-publish `preflight` job added** to `squad-npm-publish.yml`:
- Scans ALL `packages/*/package.json` for `file:` references across all dependency sections (dependencies, devDependencies, optionalDependencies, peerDependencies)
- Validates all package versions are valid semver
- Runs BEFORE smoke-test and all publish jobs — blocks the entire pipeline if violations found
- This is the gate that would have caught the v0.9.1 incident

3. **Smoke test enhanced** — Added `npm pack --dry-run` validation step for both SDK and CLI packages before the vitest smoke tests run

4. **ci-rerun.yml retained** — Added purpose documentation comment. Still useful for fork PR re-testing and infrastructure flake recovery.

5. **YAML fix** — Quoted `file:` in step names that were causing YAML parse ambiguity (both new and pre-existing)

**Pipeline dependency chain:** `preflight → smoke-test → publish-sdk → publish-cli`
8 changes: 8 additions & 0 deletions .squad/agents/eecom/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

## Learnings

### `squad version` subcommand (2026-07-15)

**Context:** Running `squad version` returned "Unknown command: version" because the subcommand was never routed in `cli-entry.ts`, even though `--version` and `-v` flags worked fine. Classic "unwired command" bug class, but for a flag-to-subcommand gap rather than a missing import.

**Fix:** Added `cmd === 'version'` to the existing `--version`/`-v` condition in `cli-entry.ts` (line ~130). Also added `version` to the help text command list. No new file in `cli/commands/` needed — this is a trivial inline handler, same as `--version`. The wiring test is unaffected since there's no separate command file.

**Pattern:** When a CLI flag (`--foo`) works but the equivalent subcommand (`foo`) doesn't, the fix is almost always a single condition addition in `cli-entry.ts`. No separate command file needed for trivial handlers.

### Privacy scrub messaging + EPERM + gitignore parent coverage (#549) (2026-07-14)

**Context:** Upgrade footer message always said "Preserves user state" even when the email privacy scrub had run — a direct contradiction of what just happened. Two related issues in the same function: EPERM on read-only `.gitattributes` would crash the upgrade, and `.gitignore` would add redundant entries already covered by parent paths (e.g. `.squad/log/` when `.squad/` was already present).
Expand Down
7 changes: 6 additions & 1 deletion .squad/agents/surgeon/charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
## How I Work

- **ISSUE TRIAGE BEFORE WORK (MANDATORY):** Add squad/priority/category labels + triage comment before any work begins on an issue.
- Releases follow a strict checklist — no improvisation
- Releases follow a strict checklist — no improvisation. Read `.squad/skills/release-process/SKILL.md` before any release work.
- **COORDINATOR DOES NOT PUBLISH.** Brady owns the release trigger. Surgeon advises, validates, and prepares — but the human publishes. Escalate, don't execute.
- **PRE-PUBLISH VALIDATION (MANDATORY):** Scan `packages/*/package.json` for `file:` and `link:` references before any tag or publish. Block if found.
- **FALLBACK PROTOCOL:** If workflow_dispatch fails twice → local publish immediately. No GitHub UI workarounds. No retry loops.
- **POST-PUBLISH SMOKE TEST (MANDATORY):** `npm install -g @bradygaster/squad-cli@latest && squad --version && squad doctor` in a clean shell after every publish. If it fails, rollback.
- Semantic versioning is law: MAJOR.MINOR.PATCH
- Never create draft GitHub Releases — `release: published` event won't fire
- SKIP_BUILD_BUMP=1 for CI builds to prevent version mutation
- NPM_TOKEN must be Automation type (not user token with 2FA) to avoid EOTP errors
- No direct commits to main or dev — PRs only
- 4-part versions (0.8.21.4) are NOT valid semver — never use them
- Set versions with `node -e` script and commit IMMEDIATELY before building
- Never use `npm -w` for publishing — always `cd` into the package directory

## Boundaries

Expand Down
67 changes: 67 additions & 0 deletions .squad/agents/surgeon/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,70 @@ v0.9.0 is a MAJOR minor version bump (0.8.25 → 0.9.0) justified by 40+ commits
- GitHub integration (CI hardening, casting alignment)

**Documentation:** Maintained strict format rules (no npx refs, no "agency" terminology, matched existing CHANGELOG style, grouped by feature subsections). CLI Terminal Rendering fixes kept from [Unreleased] as part of 0.9.0.

### v0.9.0 → v0.9.1 Release Retrospective
**Date:** 2026-03-23

**Executive Summary:** v0.9.0 published with critical defect—CLI package.json contained `"@bradygaster/squad-sdk": "file:../squad-sdk"` (local monorepo reference instead of registry version). Package broken on global install. v0.9.1 hotfix prepared in minutes but publish workflow infrastructure failures extended resolution to 8 hours (should have been 10 minutes).

**Root Causes:**
1. **Dependency Validation Gap** — No pre-publish check for `file:` references. npm workspaces automatically rewrite `"*"` → `"file:../path"` during development; this persisted in published package.
2. **GitHub Actions Workflow Cache Race Condition** — After deleting `squad-publish.yml`, GitHub workflow index didn't refresh for 10+ minutes. `workflow_dispatch` returned 422 error that persisted despite file deletion.
3. **npm Workspace Publish Broken** — `npm -w packages/squad-sdk publish` hung indefinitely (2FA auth issue on machine without authenticator app).
4. **Coordinator Decision-Making** — Retried broken `workflow_dispatch` 4+ times instead of escalating to local publish fallback sooner.

**Key Action Items:**
- A1: Add dependency validation to publish workflow (scan for `file:` refs, dry-run npm install)
- A2: Establish npm publish policy (never use `-w` for publishing; always `cd` into package directory)
- A3: Mitigate GitHub Actions cache race condition (document 15-min wait; escalate to local publish on 2nd failure)
- A4: Define publish fallback/escalation protocol (2nd workflow failure → immediate local publish)
- A5: Pre-release readiness checklist (dependency scan, CHANGELOG, tests, 2FA verify)
- A6: Post-publish smoke test (run global install; rollback if fails)

**Process Changes:**
- Change-1: Pre-publish validation mandatory (before tagging)
- Change-2: Simplified publish flow (remove manual `workflow_dispatch`; let tag trigger workflow)
- Change-3: Explicit runbook in PUBLISH-README.md (no tribal knowledge)
- Change-4: Escalation to fallback (fail-fast instead of retry loops)
- Change-5: Package validation in CI (ESLint rule to reject `file:` refs)

**Documentation:** Full retrospective in `.squad/decisions/inbox/surgeon-v091-retrospective.md` and `.squad/log/2026-03-23-v091-retrospective.md`.

**Status:** Approved for implementation. v0.9.1 published successfully (both packages verified live on npm).

---

### Release Playbook & CI Improvement Plan (2026-03-23)

Prepared comprehensive release playbook and CI improvement plan for Brady's review:

1. **Release Playbook** — Full step-by-step release procedure covering:
- Pre-release checklist (dependency validation, tests, CHANGELOG, versions, npm auth)
- Release execution (12 numbered steps from version bump to smoke test)
- Fallback procedures (422 errors, 2FA timeouts, deployment failures, rollback)
- Post-release verification checklist
- Non-negotiable rules (no improvisation, no draft releases, no 4-part versions, etc)
- Known gotchas (npm workspaces auto-rewrite, workflow cache TTL, 2FA hanging)

2. **CI Improvement Plan** — 7 GitHub issues + 4 CI cleanup actions:
- Issue A: Dependency validation gate (scan for `file:` refs before publish)
- Issue B: npm publish policy (never use `-w`, always `cd` + `--ignore-scripts`)
- Issue C: Workflow cache mitigation (15-min wait, escalation policy)
- Issue D: squad-promote workflow (dev → preview → main automation)
- Issue E: squad-preview validation (forbidden files, versions, dependencies)
- Issue F: squad version command fix (show correct CLI version)
- Issue G: Escalation policy documentation (2nd failure → local publish)
- CI cleanup: Delete ghost workflows, add pre-commit hooks, verify SKIP_BUILD_BUMP, audit NPM_TOKEN

3. **Session Log Cleanup** — Deleted 17 files from today's session logs:
- 15 files from `.squad/orchestration-log/`
- 2 files from `.squad/log/`
- Preserved retro findings in `.squad/decisions/inbox/` (surgeon-v091-retrospective.md)
- No agent history.md files deleted

**Key Lessons Learned:**
- Release playbook must be exhaustively detailed with no room for improvisation
- Fallback procedures are critical (workflow failures happen; escalate fast)
- Pre-release validation prevents 90% of publish issues
- Culture: "If the same problem happens twice, the playbook failed"
- Documentation must be user-first (Brady's perspective, not technical jargon)
Loading
Loading