feat(sdk): StorageProvider Phase 1 — interface, FSStorageProvider, security hardening (#481)#3
Merged
diberry merged 112 commits intodiberry/storage-abstractionfrom Mar 24, 2026
Conversation
- Orchestration log: 2026-03-22T12-36Z-pao.md — PAO completed full docs catalog audit - Session log: 2026-03-22T12-36Z-docs-catalog-audit.md — session summary - Merged .squad/decisions/inbox/pao-docs-audit.md into decisions.md - Updated PAO history.md with docs audit learnings (15 orphans, 0 dead links, 5 top actions) - Deleted inbox file - Docs audit found critical nav gaps, stale content, duplication; formalized 5 action items Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Orchestration: Booster completed whatsnew.md version sync automation (2026-03-22T12:46Z) - Merged decision: whatsnew auto-sync via prebuild script + Vitest test gate - Updated PAO history: Docs audit finding #1 (stale version) resolved - Removed merged inbox decision: booster-whatsnew-sync.md whatsnew.md heading now syncs on every build (local + CI), keeping release docs current with package.json version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Orchestration log: 2026-03-22T12-55Z-pao.md (PAO DevRel spawn) - Session log: 2026-03-22T12-55Z-docs-fixes.md - Inbox: clean (no files to merge) All 4 fires resolved. Build tests passing (23/23).
…radygaster#515) Adds rate limit protection to Ralph's watch command as an additive patch on top of the existing watch flow. No existing functions are modified. Changes: - gh-cli.ts: +ghRateLimitCheck(), +isRateLimitError() helpers - watch.ts: +CircuitBreakerState type, persistence helpers - watch.ts: +executeRound() wrapper gates existing runCheck through pre-flight quota checks (traffic light + predictive CB) - watch.ts: +roundInProgress flag prevents overlapping setInterval rounds - 16 new tests: state machine transitions, race guard, isRateLimitError State machine: closed → open (quota critical) → half-open (cooldown expires) → closed (2 consecutive successes) or re-open (429 during probe). Cooldown doubles on each failure (2m → 4m → ... → 30m cap). State persists to .squad/ralph-circuit-breaker.json. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…uad-per-pod) Adds SQUAD_POD_ID and SQUAD_DEPLOYMENT_MODE env vars for pod-specific capability routing. Pod-specific manifests override shared manifests. Closes bradygaster#514 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Linux chmod 444 returns EACCES, not EPERM. Handle both codes for cross-platform compatibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
# Conflicts: # docs/src/content/docs/guide.md # docs/src/content/docs/tips-and-tricks.md # docs/src/content/docs/tour-first-session.md
- Inject __VERSION__, __COMMIT_SHA__, __BUILD_DATE__ via Vite define in astro.config.mjs
- Display v{version} · {sha7} · {date} in Footer.astro (xs muted text)
- Pass SQUAD_VERSION and GITHUB_SHA env vars in squad-docs.yml build step
- Add env.d.ts to declare globals for TypeScript
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Before: bradygaster.github.io/squad/docs/get-started/installation/ footer After: Astro preview server with full CSS rendering Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Screenshots belong in PR comments, not committed to the branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Flight review: '0.9.1' hardcode would drift after next release. Empty string lets the Vite define fall through to package.json. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes docs-quality CI failure on PR bradygaster#568 which adds KEDA scaling docs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds complete Chinese translation of README.md based on the excellent work by @JasonYeYuhe in PR bradygaster#507. This update brings the Chinese README current with all recent additions to the English README. Updates include: - New 'Upgrading' section (two-step upgrade process) - 'What the Shell Does' subsection (real-time visibility, routing, etc.) - 'Samples' section (eight working examples) - 'SDK-First Mode' section (experimental TypeScript config) - 'Monorepo Development' section (building, testing, linting, publishing) - 'SDK documentation' section with reference links - Updated 'upgrade' command description with --global flag - Language switcher added to both READMEs Translation preserves JasonYeYuhe's terminology choices for technical concepts like '智能体' (agent), '协调员' (Coordinator), '花名册' (Roster), '选角' (Casting), and '书记员' (Scribe). Supersedes bradygaster#507 Co-authored-by: JasonYeYuhe <69640321+JasonYeYuhe@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merging: CI green, docs version badge.
…-dual-mode-capabilities feat(capabilities): dual-mode deployment — agent-per-node + squad-per-pod (bradygaster#514)
…-rate-limit-watch-v2 feat(watch): circuit breaker integration — additive patch (bradygaster#515)
- New: capability-routing.md — needs:* label routing and machine capability declaration - New: rate-limiting.md — cooperative rate limiting and RAAS traffic-light pattern - New: cross-machine.md — cross-machine coordination for multi-machine Squad deployments - New: keda-scaling.md — KEDA external scaler template for agent autoscaling - Updated: model-selection.md — add Economy Mode section - Updated: navigation.ts — add four new feature pages to nav - Updated: test/docs-build.test.ts — add new pages to EXPECTED_FEATURES Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Flight review blocker — config file was .squad/config.json, should be machine-capabilities.json per PR bradygaster#520's loadCapabilities() implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a new skill for coordinating work between squad agents running on different machines (laptop, DevBox, Azure VMs, etc.). **Pattern:** Git-based task queuing + GitHub Issues supplement The skill defines: - YAML task file format for cross-machine work assignment - YAML result file format for execution outcomes - Security validation pipeline (schema, command whitelist, resource limits) - Ralph Watch integration (automatic poll-and-execute cycle) - Urgent task routing via GitHub Issues + machine-specific labels - Error handling for failures, stalls, and network issues This pattern enables multi-machine squad deployments to divide work by capability (e.g., GPU workloads on a powerful remote machine) without human intervention in the handoff. Closes: N/A (new skill contribution from tamirdresher/squad fork)
…ature-docs docs: v0.9.0 missing feature docs (capability routing, rate limiting, economy mode, cross-machine, KEDA)
…-readme docs: update Chinese README translation
…ne-coordination feat(skills): add cross-machine-coordination skill for multi-machine squad deployments
Links to https://github.com/tamirdresher/squad-skills/tree/main/workshop from getting started and resources pages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…kill During StorageProvider Phase 1, a cross-platform audit found that startsWith() is case-sensitive but Windows and macOS filesystems are case-insensitive. This gap was missed by 4 rounds of security review because the existing skill covered timestamps, git commands, and path separators — but not path comparison semantics. Adding platform-aware comparison pattern and anti-pattern example so future agents catch this automatically via skill-aware routing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
docs: add link to Tamir's Squad Skills Workshop
…kill (bradygaster#574) docs: add case-insensitive path comparison to windows-compatibility skill
diberry
pushed a commit
that referenced
this pull request
Mar 23, 2026
Documents the Time-of-Check Time-of-Use race condition inherent in exists() → read() patterns. Callers should rely on read() returning undefined rather than pre-checking with exists(). Addresses Phase 1 backlog item #2 (RETRO finding #3). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…radygaster#577) * chore(.squad): session wrap-up — inbox merge, logs, history updates Merged 12 decision inbox entries into decisions.md. Logged mega-session covering release recovery, docs fix, 10 PR merges, discussion triage, and release hardening. Updated agent histories with session learnings. Deleted inbox files after merge: - booster-ci-audit.md, booster-ci-cleanup.md - copilot-directive-2026-03-23T09-56.md, copilot-directive-2026-03-23T10-08.md - copilot-directive-no-npx.md - eecom-version-cmd.md - pao-discussion-triage-2026-03-23.md, pao-npx-purge.md, pao-readme-slim.md - pao-v090-blog.md - surgeon-v090-changelog.md, surgeon-v091-retrospective.md Updated files: - .squad/decisions.md (12 decision entries merged) - .squad/identity/now.md (current state updated) - .squad/log/2026-03-23T22-00-00Z-mega-session-wrapup.md (new) - .squad/agents/flight/history.md (issue filing patterns, governance directives) - .squad/agents/eecom/history.md (CLI version subcommand pattern) - .squad/agents/booster/history.md (CI audit and preflight patterns) - .squad/agents/surgeon/history.md (release governance rules, retrospective) - .squad/agents/pao/history.md (discussion triage patterns, Teams MCP urgency) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(shell): robust agent name extraction with multi-pattern fallback (bradygaster#577) - Fix TS compilation errors in agent-name-parser.ts (strict null checks) - Add fallback in else branch: show trimmed description text instead of generic 'Dispatching to agent...' hint when name extraction fails - Parser tries 3 patterns: emoji+name:colon, name:colon anywhere, fuzzy word-boundary match against known agent names Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs(.squad): VOX history + decision for bradygaster#577 agent name fix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: sync squad.agent.md template copies after bradygaster#577 name param fix Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Orchestration Log: Issue bradygaster#577 agent name extraction completion Agent orchestration complete for bradygaster#577: - VOX: Fixed agent name extraction in shell/index.ts with 3-tier cascading patterns - FIDO: Extracted parser to agent-name-parser.ts (30 tests, all passing) - Procedures: Updated all spawn templates with mandatory name parameter Actions: - Created 3 orchestration logs (.squad/orchestration-log/) - Created session log (.squad/log/2026-03-23T23-15-issue-577-agent-names.md) - Merged 3 decision inbox files to .squad/decisions.md (3 new decision entries) - Deleted inbox files after merge - Appended team updates to VOX, FIDO, Procedures history.md files All decisions merged. Agent IDs now display correctly in Copilot CLI tasks panel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Merged 82 decisions from .squad/decisions/inbox/ to .squad/decisions.md - Created orchestration logs for Flight (Phase 2 plan) and Explore (parser catalog) - Created session log for Phase 2 kickoff (Flight + Explore outcomes) - Cleaned up all inbox files after merge - Append-only pattern used for decisions.md (318KB+) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erface Phase 2 files were scattered across branches during multi-agent work. Recovered source from dist/ artifacts and cherry-picked committed files. - Domain types: StateError hierarchy, 10 domain interfaces - Collection map: compile-time type safety (CollectionEntityMap) - Schema: COLLECTION_PATHS mapping + resolveCollectionPath() - IO layer: 5 parse/serialize modules (charter, history, decisions, routing, team) - Handles: AgentHandle factory with charter/history/update - Collections: 7 facade classes (Agents, Decisions, Routing, Team, Skills, Templates, Log) - SquadState: top-level facade with create() factory - Tests: 43 passing state tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Avoids naming conflicts with existing config/sharing exports by using explicit named exports instead of wildcard re-export. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
FIDO coverage audit: error hierarchy, schema resolution, IO round-trips, AgentHandle edge cases, Unicode/i18n support. 83 total state tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Flight: Architecture review APPROVE WITH NOTES - CONTROL: Type safety audit APPROVE - FIDO: Coverage audit APPROVED FOR MERGE Merged 9 decision inbox files to decisions.md Deleted inbox files after merge Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rovider Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2948578 to
5078f08
Compare
Owner
Author
Team Review — Unanimous ✅ MERGEReviewers
Phase 1: StorageProvider — ✅ Complete
Phase 2: SquadState Facade — ✅ Complete
Test Results
Follow-up Issues (none block merge)
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#10) Add 22 new tests covering hostile inputs to appendHistory() and parseHistory(): appendHistory adversarial tests (8): - Code blocks with ## Fake Header in preceding sections - Empty sections (adjacent ## headers with no content) - Excessive whitespace between sections - Sections with existing ### sub-headers - Missing target section (auto-create at end) - Unicode content (emoji, CJK, RTL) - Very long sections (55+ entries) - Duplicate section headers (degenerate case) parseHistory adversarial tests (7): - Empty string input - Whitespace-only input - Title-only file (no ## sections) - ##NoSpace malformed header (correctly ignored) - ## (trailing space) cross-line regex consumption (bug documented) - ## alone cross-line regex consumption (bug documented) - Unrecognized section names not mapped to known fields BUG DISCOVERED: headerRegex /^##\s+(.+?)\s*$/gm allows \s+ to consume newlines, causing cross-line matching. Malformed headers like '## ' or '##' followed by blank lines consume the NEXT valid section header. Tests document actual behavior for future fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Closes #8) ParseError wrapping was implemented across two concurrent agent commits. This commit documents the changes for traceability. Changes in commit 8811777 (ConfigCollection): - collections.ts: Added ParseError import, wrapped parseDecisions(), parseRouting(), parseTeam() calls with try/catch -> ParseError Changes in commit dfaf6fc (adversarial tests): - handles.ts: Added ParseError import, wrapped parseHistory() and parseTeam() (in update()) calls with try/catch -> ParseError - squad-state-gaps.test.ts: Added 6 ParseError wrapping tests (DecisionsCollection, RoutingCollection, TeamCollection, AgentHandle.history, AgentHandle.update, non-Error cause) Pattern applied at every facade parse boundary: try { return parseX(content); } catch (err) { throw new ParseError(collection, err instanceof Error ? err.message : String(err), { cause: err }); } Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- routing-io: parse ## Module Ownership table into Map<string, string> - team-io: extract project context between title and ## Members - collections: wire parsed data through toRoutingConfig/toTeamConfig - handles: adapt to new ParsedTeam return type - tests: verify populated and empty cases for both fields - io/index: export new ParsedRouting and ParsedTeam types Closes #4 Closes #9 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
#5) Phase 3 Wave 1 — migrate low-risk CLI reads to StorageProvider abstraction. spawn.ts: - loadAgentCharter() now async, reads via SquadState.agents.get(name).charter() - Replaces readFileSync with StorageProvider-backed AgentHandle - Same error messages preserved for backward compatibility coordinator.ts: - buildCoordinatorPrompt() now async, reads via FSStorageProvider.read() - Replaces readFileSync for team.md and routing.md raw content - Extracted noTeamFallback constant to reduce duplication index.ts (shell): - All 3 call sites updated with await (warm-up, dispatch, agent spawn) Tests updated across 3 files (228 tests, all passing). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Phase 3 Wave 2 — shell boot path migration. initialize(): - Reads via async FSStorageProvider.read()/exists() for team.md, .squad/ directory, and .init-prompt checks - Replaces fs.existsSync, fs.statSync, fs.readFileSync with StorageProvider-backed async operations - Same error messages preserved for backward compatibility loadWelcomeData(): - Reads via FSStorageProvider sync methods (readSync, existsSync) to route through StorageProvider while preserving synchronous API (required by React useState initializer in App.tsx) - Replaces fs.existsSync + fs.readFileSync for team.md and now.md - .first-run marker delete stays as raw unlinkSync (write operation) All 228 shell/lifecycle tests passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ads (#5) Phase 3 Wave 2 — shell boot path migration. status command (line 412): - Replaces fs.existsSync(globalSquadDir) with await storage.exists() via FSStorageProvider instance cost command (line 451): - Replaces fs.existsSync(globalSquadDir) with await storage.exists() via FSStorageProvider instance Removes raw 'node:fs' import — all reads now routed through StorageProvider abstraction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace node:fs/promises (mkdir, writeFile, readFile) and node:fs (existsSync) with FSStorageProvider async/sync methods. StorageProvider.write() handles recursive directory creation, removing the need for explicit mkdir calls. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace fs.readFileSync/writeFileSync/existsSync with FSStorageProvider sync methods. Residual mkdirSync (empty dir scaffolding) and renameSync (archive move) kept with TODO comments — no StorageProvider equivalent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace fs.readFileSync/writeFileSync/existsSync/readdirSync with FSStorageProvider equivalents. Residual statSync().isDirectory() call kept with TODO — not available in StorageProvider interface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace all fs.existsSync/readFileSync/writeFileSync/mkdirSync with FSStorageProvider equivalents. StorageProvider.writeSync() handles recursive dir creation, simplifying writeFiles(). checkDrift() now uses readSync() returning undefined instead of existsSync+readFileSync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…berry/storage-abstraction)
Owner
Author
✅ Phase 2 Complete — Team Verdict (PRD bradygaster#481)Phase-by-Phase Status
What Phase 2 Delivered
PRD Success Metrics
Test Results
Team Approvals
What's Next (Phase 3: CLI Migration)Phase 3 scope: Replace raw Posted by Squad Coordinator on behalf of the team — Flight, EECOM, FIDO, Scribe. |
This was referenced Mar 27, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
StorageProvider Phase 1 — TDD
Implements the core storage abstraction for squad-sdk per #481.
What
TDD Commits
Review Status
Decisions
squad obo dina