Skip to content

Commit 638a9da

Browse files
fboucherCopilotCopilotCopilot
authored
Release: Merge v-next into main (#198)
* Adds room editing dialog Adds a dialog to edit room properties, specifically the position of doors. This allows users to adjust room layouts and door placements after a room has been created. * Enables door repositioning in room editor Implements functionality to move door positions within the room editor dialog. This allows users to fine-tune door placement within a room, enhancing the level design process. It dynamically shows the correct axes of movement by looking at door direction and only displaying the perpendicular movement axes. * Enables moving exits in room editor Allows adjusting the position of exits on walls within the room editor. This change introduces functionality to dynamically update exit positions, providing a more intuitive and interactive editing experience. The "Modal" property of the dialog was set to false to allow background interaction. * Improves door placement in room editor Replaces directional buttons with a slider for precise door positioning on walls. This change allows users to visually adjust the door's location within the room editor dialog, enhancing the user experience. * add id on div to identify map context menu * Improves map menu placement. Makes the map menu stick to the top of the screen to prevent it from scrolling off-screen during gameplay. * Initial plan * Implement maps-menu enable/disable based on nextRoom draft state Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> * When dialogue cancelled nextroom should be set to null * Disables room buttons when no room exists Disables the "Add Room" and "Edit Room" buttons when there isn't a room to add or edit. This prevents the user from interacting with those features when they are not available and improves the user experience. * Corrects door placement on the map Adjusts the positioning of doors on the map to ensure they are placed outside the adjacent room's boundary. Simplifies door drawing logic, ensuring doors are consistently drawn as full squares. * Fixes typo in new room dialog Corrects a typo in the new room dialog where "gameTurn" should be "get". This improves the readability of the generated room description for the user. * Corrects door placement on the map Adjusts the door coordinate calculation to ensure doors are placed correctly relative to rooms. The canvas drawing logic was also reviewed, and unnecessary offset code for vertical doors was removed. * Updates save game count to use adventure previews fixes #119 Changes the implementation of GetSaveGameCount to utilize the GetAdventurePreviews method, providing a more accurate count of saved games. Adds .gitignore file for Rider IDE to ignore IDE specific files. * Adds adventure deletion functionality Implements the ability to delete saved adventures. This change introduces a delete endpoint in the service and a corresponding button in the adventure picker component. When a user clicks the delete button, the selected adventure is removed and the adventure list is refreshed. * Fixes adventure deletion event handling Stops event propagation on the adventure deletion button to prevent unintended row selection when deleting an adventure. Also, adds project-level IDE configuration files. * Refactors adventure preview loading Improves the adventure picker component by extracting the adventure preview loading logic into a separate method. This change enhances code readability and maintainability. Also, this fixes a potential UI update issue by explicitly calling StateHasChanged after loading previews when deleting an adventure. * Adds adventurer deletion functionality Enables the deletion of adventurers, ensuring that an adventurer can only be deleted if it is not currently associated with any existing adventures. This prevents data integrity issues and provides a safeguard against accidentally deleting adventurers that are actively used in a game. * Add "Start a new fight" button to reset combat screen - fixes #116 (#124) * Initial analysis of issue #116 - combat screen reset functionality Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> * Implement "Start a new fight" button to reset combat screen - fixes #116 Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> * Add adventure name property and use adventurer ID reference (#126) * Initial plan * Add adventure name feature - update domain models and services Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> * Remove foreign key constraint from adventures table Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: FBoucher <2404846+FBoucher@users.noreply.github.com> * Add complete Dungeon theme with custom backgrounds, text, and accent colors (#128) * Initial plan * Add Dungeon theme option to Settings page Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> * Address code review feedback - improve theme persistence Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> * Updates Aspire SDK and package versions Updates the Aspire.AppHost.Sdk version in the AppHost project file. Adds a Directory.Packages.props file to manage package versions centrally, and updates various Aspire and related package versions to their latest releases, ensuring consistency and compatibility across the solution. * Implement full Dungeon theme with custom backgrounds and text colors Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> Co-authored-by: fboucher <fboucher@outlook.com> * Implement door type drawing functions with lock/unlock feature for dungeon map (#129) * Implement door details with different door types (Archway, Wooden, Metal, Reinforced, Curtain, Portcullis, Stone Slab) Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: fboucher <2404846+fboucher@users.noreply.github.com> * Fix: Addresses combobox selection and map debug issues (#130) Addresses an issue where combobox selections were not handled correctly. Now correctly passes the selected object instead of just the ID. Also adds debug logging to help resolve an intermittent map drawing issue. * Upgrades .NET and Aspire dependencies (#132) * upgrade in progress * feat(dab): Configure connection string via environment variable Configures the Data API Builder (DAB) connection string using an environment variable. This change ensures that the connection string for the database is properly set within the DAB configuration, especially during upgrade scenarios. It removes the port from the DAB template and constructs the connection string dynamically in code, referencing the MySQL resource's properties. * Replaces bind mount with file copy Replaces the bind mount approach for database initialization with a simpler file copy mechanism. This change simplifies the setup process, especially during upgrades, by ensuring that database scripts are copied directly into the container. * Implements combat turn management. (#134) Adds logic to manage combat turns, including identifying the current fighter and alternating turns between adventurer and creature. Introduces a dialog to select the first fighter and displays the current turn information. Fixes: #133 * Implements game over and victory conditions (#136) Adds logic to handle adventurer and creature defeats, displaying appropriate messages. Disables user interaction after combat ends to prevent further actions. Resets health depletion flags and UI elements on new fight start. Fixes #135 * Adds damage dice rolling functionality (#138) Implements the ability to roll damage dice within the combat page. This allows players to simulate damage rolls using 1D6 or 2D6 dice. Issue #137 * Removes seed adventurers from database (#139) * Removes demo adventurers from seed data Removes the demo adventurers from the database seed data. This prevents the creation of unnecessary or test adventurers when the database is initialized, ensuring a cleaner and more realistic initial state. * Removes demo adventurers from seed data The demo adventurers are no longer needed in the database seed data. This commit removes them. * Enables local Docker deployment (#140) * Adds Docker configuration for local development Sets up Docker Compose to orchestrate the application, database, and data api builder services for local development. Includes Dockerfile for the web client. Ensures database creation if it doesn't exist. Includes `.dockerignore` to exclude unnecessary files during image builds. Sets up `.env.example` with required environment variables * Enables running the app locally with Docker Provides a `docker-compose.yml` file for easy local deployment using Docker. Adds Dockerfiles for the database, Data API Builder (DAB), and web app components. Includes an `.env.example` file with configurable environment variables. Publishes images to Docker Hub upon tagging a commit. Fixes #91 * Improves adventurer creation flow (#143) * Improves adventurer creation experience Enhances the adventurer creation page by: - Removing unnecessary conditional rendering for weapons, streamlining the weapon selection process. - Updates the manoeuvre selection to provide more guidance to the user, including a dynamic placeholder text and label displaying the current weapon. - Sets default values to avoid null reference exceptions, improving robustness. - Sets default row size on the AdventurerPicker component to medium for better UI consistency Fixes #142 * Navigates to adventure page after character creation Updates the character creation process to navigate to the adventure page with the newly created adventurer's ID. This enables a smoother transition to gameplay. Adds auto-selection of the created adventurer. Fixes #142 * Renames Preview classes to DTO (#144) Renames the `*Preview` classes to `*DTO` to better reflect their purpose as Data Transfer Objects. This change improves clarity and consistency in the codebase. * Positions new rooms automatically on map (#147) Calculates the origin coordinates for newly added rooms based on the selected exit door of the current room, ensuring proper alignment and visual consistency on the map. Adds a visual highlight to the "Add Room to Map" button when a new room is available to be added. Improves map generation workflow by automating room placement. Related to #146 * Prevents duplicate unique rooms on a level (#150) Implements a mechanism to prevent the same unique room from appearing multiple times on the same dungeon level. Introduces a `_usedUniqueRoomsByLevel` dictionary in the `Dungeon` class to track used unique room IDs per level. The `TryResolveUniqueRoomConflict` method in `GameTurn` now re-rolls unique rooms if they've already been used on the current level, up to a maximum number of attempts. Adds `NewRoomDialogData` to pass both the `Room` and `Dungeon` to the NewRoomDialog component. Fixes #149 * fix: standardize Blazor parameter capitalization (#45) (#155) - Adventurer.razor: `state` → `State` with private `_state` backing field - Play.razor: `adventureId` → `AdventureId` with private `_adventureId` backing field Closes #45 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Enhance map graphics with dungeon aesthetic (#156) * feat: enhance map graphics with parchment background, stone textures, and 3D walls Visual improvements to dungeon map (no external libraries): - Parchment-style background with gradient and subtle age texture - 3D beveled walls with shadow effect - Stone tile floor pattern with brick-style layout - Warm torch glow effect for current room - Enhanced door visuals with thicker wall lines - Special main entrance marker with decorative arch - Refined grid dots on warmer color palette - Configurable MapTheme color constants * docs: update Lambert history and add map graphics decision * Scribe: Document Lambert's map graphics work - Add orchestration log: 2026-02-28T194415-lambert.md - Add session log: 2026-02-28T194415-map-graphics-improvement.md - Merge decisions from inbox (pure Canvas 2D, user directive) - Update Dallas history with Lambert's frontend changes * feat: add dice roll animations (#157) - Added tumbling animation with random face cycling (600ms) - Added single-flip animation for shift buttons - Added doubles celebration with sparkles and stars - Fixed NewRoomDialog to always render dice for animation triggers - Pure CSS/JS implementation, no external libraries * feat: map pan controls for large dungeon exploration (#158) * .squad: Orchestration & session logs for dice animations & map panning - Orchestration logs for Lambert agents 2-5 (dice animations + map panning) - Session log summarizing dice animation work and viewport panning features - Merged decision inbox (viewport panning implementation) into decisions.md - Updated Lambert's history.md with completion details and critical patterns Feature summary: - Dice Roll Animations: Added roll, flip, doubles celebration animations (Agent 2-4) - Map Viewport Panning: Implemented with arrow buttons, keyboard support (Agent 5) - Critical pattern documented: Always-render Dice components with CSS visibility * feat: add map pan controls with arrow buttons and keyboard support - Add viewport offset tracking (viewportOffsetX, viewportOffsetY) in canvasTools.js - Pan ~2 grid squares per click via arrow buttons or keyboard arrow keys - Add Center button to snap viewport to current room - Add Reset button to return to origin (0,0) - Modify DrawRoom() and DrawDoor() to apply viewport offset - Add C# interop methods in MapTools.cs for Blazor components - Add pan control UI to Play.razor with directional pad layout Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: combat/play crash and missing content at high zoom (fixes #114) (#159) * fix: add FluentMenuProvider to MainLayout to fix zoom crash (closes #114) FluentOverflow renders a FluentMenu dropdown when items overflow (e.g. at high zoom levels). FluentMenu requires FluentMenuProvider to be registered in the layout, otherwise it throws ArgumentNullException and disconnects the Blazor circuit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: enable horizontal scroll on body content when zoomed in At high zoom levels content overflows the viewport horizontally. Adding overflow-x: auto to .body-content allows the user to scroll horizontally to access all content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: force overflow-x: auto to override FluentUI scoped CSS hidden rule FluentBodyContent's scoped CSS sets overflow-x: hidden with a [b-9l28a7kahd] attribute selector, which wins over our class-only rule. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chore: auto-strip .squad/.squad-templates/.copilot from main on merge GitHub Actions workflow that runs on every push to main and removes dev-only tooling directories (.squad, .squad-templates, .copilot). These are needed for development on v-next but should never land in the production branch that users see. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Enriches dungeon data and table viewer (#165) * more data related to rooms and metatables * feat: expand creature data and add dungeon lookup tables (fixes #162) Update creature schema to support longer text fields and populate the database with extensive new creature entries and randomized loot lookup tables. * feat: map and display encounter data in room details (fixes #162) Add an Encounter property to the MappedRoom model and update the web client to show encounter information in the room summary. This commit also updates the development environment to .NET 10.0.100 and adds VS Code launch configurations for local development. * fix issue with iaut1 table and all all other meta_table * add level column to meta_table and update data inserts * enhance MetaTables and TableViewer components with improved data handling and UI updates * clean-up * fix: standardize CSV formatting and correct room data tables (fixes #162) Standardizes all CSV data files by removing unnecessary double quotes and updates the `l1w` and `l1wo` tables to correctly list NPC encounters instead of weapons. * squad clean-up * feat: add release and manual triggers to image publishing workflow Update the workflow to trigger on release publication and manual dispatch. This allows users to publish images for specific git tags manually and ensures images are built when a formal release is created. * missing tables used in level 1 * feat: show app version in footer (#169) show app version in footer (#161) * feat: add name and level filtering to creature picker (#163) (#175) Update the creature selection grid to support filtering by name and level, allowing users to more easily find specific creatures. This includes adding search boxes to column options and logic to filter the data source. * feat: add XP delta widget to adventurer sheet (#177) * feat: add XP delta widget to adventurer sheet (#164) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * align the txtboxs and buttons --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update aspire done! (#179) * update version for release * feat: complete adventurer character sheet (#173) Add all missing domain model fields to AdventurerCard.razor: - Discipline stat - Status effects (Bloodied, Fever, Soaked, Pneumonia) - Currency (Gold, Silver, Copper) - Rations count - Quest tracking (Legend Status, Prisoners, Treasures, Side Quests) - Favor of the Gods (all six deities) - Weapon display All 31 domain model properties now visible in the UI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * moving components around to mimik the sheet * all components ar ethere. still need to tuning * docs: add character sheet to feature roadmap (#173) * Enhances Adventurer Card and Combat Page Layout (#182) * feat: enhance AdventurerCard with level and health display, and add legend status level tracker Co-authored-by: Copilot <copilot@github.com> * feat: adjust card widths and enhance AdventurerCard layout for better visibility Co-authored-by: Copilot <copilot@github.com> --------- Co-authored-by: Copilot <copilot@github.com> * Enhances player inventory management and expands game items (#185) * feat: add interactive magic potion inventory management This feature allows players to dynamically manage their adventurer's magic potions. It introduces a new `SelectPotionDialog` for choosing potions from the available list and enhances the `MagicPotions` component with functionality to add new potions and remove ('use') existing ones, providing a fully interactive inventory. A new `GetMagicPotions` service endpoint was added to fetch all available potions. * feat: enhance AdventurerCard and MagicPotions components with player change handling and potion management * feat: implement MagicScroll selection dialog and enhance MagicScrolls component with add/delete functionality * fix: update icon for adding large and heavy items in AdventurerCard * feat: enhance magic scrolls and potions with new entries and detailed attributes * Add project cache files for AppHost and ServiceDefaults - Created AppHost.csproj.lscache to cache language service data for the AppHost project. - Created ServiceDefaults.csproj.lscache to cache language service data for the ServiceDefaults project. - Both files are auto-generated and improve performance for C# Dev Kit. * feat: add dialog for editing large and heavy items and update AdventurerCard component * feat: update magic scrolls and potions with new descriptions and costs; enhance AdventurerCard for large and heavy item management * update aspire and version * feat: add is_initial column to armour and magic scroll data models and implement retrieval services * feat: add armour piece selection dialog and update gitignore for agent tooling (#187) * fix: update footer links in MainLayout for documentation and personal site * Remove build warnings (issue #189) (#190) * Fix warnings for issue #189: update packages and code fixes to remove build warnings\n\n- Suppress NU1902 temporarily in Directory.Packages.props\n- Fix enum switch exhaustiveness, await async invocations, remove unused fields, and null-safety fixes\n\nResolves: #189\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: update Aspire, OpenTelemetry, and FluentUI dependencies * remove the suppressor NU1902 packages upgraded * fix: correct roll reference for gem transformation in iaut1.csv * feat: use all door types from room definition (#191) (#193) * feat: use all door types from room definition (closes #191) * feat: add floating map legend panel with door type icons * fix: explicitly expose drawLegendDoor on window for Blazor JS interop * fix: center legend door icons in canvas by passing top-left to DrawDoorType * feat: add locked doors logic (issue #148) (#195) - Add LockRoll to MappedRoom and RollForLocks action in GameTurn - Add Locks step to NewRoomDialog wizard with 1D6 roll - Skip Locks step when room has 0 exits or is a corridor - Update AssignExits to apply locking rules based on D6 result: 6 = all locked, 5 = reinforced locked, 4 = metal locked - Disable locked door buttons in SelectDoorDialog - Add guard in Play.razor to prevent navigating to unmapped rooms * Implement lockpicking and patrol wait features (Issue #192) (#196) * Implement lockpicking and patrol wait features (Issue #192) * Update NewRoomDialog locks step message to show current room context * Refine NewRoomDialog locks step message to only mention exits type and add exits type to the Summary panel * Show locked/unlocked status in the Summary panel of NewRoomDialog * Fix CS8602 warning on null dereference of ExitsType in NewRoomDialog * chore: update Aspire dependencies to 13.3.5 and lowercase room exit descriptions * Refactor patrol wait to roll 1D6 on l1p table and treat as always hostile * refactor: update patrol resolution to roll 2d6 and support non-hostile encounters --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <copilot@github.com>
1 parent a49caa1 commit 638a9da

157 files changed

Lines changed: 16209 additions & 57 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.copilot/mcp-config.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"mcpServers": {
3+
"EXAMPLE-trello": {
4+
"command": "npx",
5+
"args": [
6+
"-y",
7+
"@trello/mcp-server"
8+
],
9+
"env": {
10+
"TRELLO_API_KEY": "${TRELLO_API_KEY}",
11+
"TRELLO_TOKEN": "${TRELLO_TOKEN}"
12+
}
13+
}
14+
}
15+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
name: "agent-collaboration"
3+
description: "Standard collaboration patterns for all squad agents — worktree awareness, decisions, cross-agent communication"
4+
domain: "team-workflow"
5+
confidence: "high"
6+
source: "extracted from charter boilerplate — identical content in 18+ agent charters"
7+
---
8+
9+
## Context
10+
11+
Every agent on the team follows identical collaboration patterns for worktree awareness, decision recording, and cross-agent communication. These were previously duplicated in every charter's Collaboration section (~300 bytes × 18 agents = ~5.4KB of redundant context). Now centralized here.
12+
13+
The coordinator's spawn prompt already instructs agents to read decisions.md and their history.md. This skill adds the patterns for WRITING decisions and requesting help.
14+
15+
## Patterns
16+
17+
### Worktree Awareness
18+
Use the `TEAM ROOT` path provided in your spawn prompt. All `.squad/` paths are relative to this root. If TEAM ROOT is not provided (rare), run `git rev-parse --show-toplevel` as fallback. Never assume CWD is the repo root.
19+
20+
### Decision Recording
21+
After making a decision that affects other team members, write it to:
22+
`.squad/decisions/inbox/{your-name}-{brief-slug}.md`
23+
24+
Format:
25+
```
26+
### {date}: {decision title}
27+
**By:** {Your Name}
28+
**What:** {the decision}
29+
**Why:** {rationale}
30+
```
31+
32+
### Cross-Agent Communication
33+
If you need another team member's input, say so in your response. The coordinator will bring them in. Don't try to do work outside your domain.
34+
35+
### Reviewer Protocol
36+
If you have reviewer authority and reject work: the original author is locked out from revising that artifact. A different agent must own the revision. State who should revise in your rejection response.
37+
38+
## Anti-Patterns
39+
- Don't read all agent charters — you only need your own context + decisions.md
40+
- Don't write directly to `.squad/decisions.md` — always use the inbox drop-box
41+
- Don't modify other agents' history.md files — that's Scribe's job
42+
- Don't assume CWD is the repo root — always use TEAM ROOT
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
name: "agent-conduct"
3+
description: "Shared hard rules enforced across all squad agents"
4+
domain: "team-governance"
5+
confidence: "high"
6+
source: "reskill extraction — Product Isolation Rule and Peer Quality Check appeared in all 20 agent charters"
7+
---
8+
9+
## Context
10+
11+
Every squad agent must follow these two hard rules. They were previously duplicated in every charter. Now they live here as a shared skill, loaded once.
12+
13+
## Patterns
14+
15+
### Product Isolation Rule (hard rule)
16+
Tests, CI workflows, and product code must NEVER depend on specific agent names from any particular squad. "Our squad" must not impact "the squad." No hardcoded references to agent names (Flight, EECOM, FIDO, etc.) in test assertions, CI configs, or product logic. Use generic/parameterized values. If a test needs agent names, use obviously-fake test fixtures (e.g., "test-agent-1", "TestBot").
17+
18+
### Peer Quality Check (hard rule)
19+
Before finishing work, verify your changes don't break existing tests. Run the test suite for files you touched. If CI has been failing, check your changes aren't contributing to the problem. When you learn from mistakes, update your history.md.
20+
21+
## Anti-Patterns
22+
- Don't hardcode dev team agent names in product code or tests
23+
- Don't skip test verification before declaring work done
24+
- Don't ignore pre-existing CI failures that your changes may worsen
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
name: "architectural-proposals"
3+
description: "How to write comprehensive architectural proposals that drive alignment before code is written"
4+
domain: "architecture, product-direction"
5+
confidence: "high"
6+
source: "earned (2026-02-21 interactive shell proposal)"
7+
tools:
8+
- name: "view"
9+
description: "Read existing codebase, prior decisions, and team context before proposing changes"
10+
when: "Always read .squad/decisions.md, relevant PRDs, and current architecture docs before writing proposal"
11+
- name: "create"
12+
description: "Create proposal in docs/proposals/ with structured format"
13+
when: "After gathering context, before any implementation work begins"
14+
---
15+
16+
## Context
17+
18+
Proposals create alignment before code is written. Cheaper to change a doc than refactor code. Use this pattern when:
19+
- Architecture shifts invalidate existing assumptions
20+
- Product direction changes require new foundation
21+
- Multiple waves/milestones will be affected by a decision
22+
- External dependencies (Copilot CLI, SDK APIs) change
23+
24+
## Patterns
25+
26+
### Proposal Structure (docs/proposals/)
27+
28+
**Required sections:**
29+
1. **Problem Statement** — Why current state is broken (specific, measurable evidence)
30+
2. **Proposed Architecture** — Solution with technical specifics (not hand-waving)
31+
3. **What Changes** — Impact on existing work (waves, milestones, modules)
32+
4. **What Stays the Same** — Preserve existing functionality (no regression)
33+
5. **Key Decisions Needed** — Explicit choices with recommendations
34+
6. **Risks and Mitigations** — Likelihood + impact + mitigation strategy
35+
7. **Scope** — What's in v1, what's deferred (timeline clarity)
36+
37+
**Optional sections:**
38+
- Implementation Plan (high-level milestones)
39+
- Success Criteria (measurable outcomes)
40+
- Open Questions (unresolved items)
41+
- Appendix (prior art, alternatives considered)
42+
43+
### Tone Ceiling Enforcement
44+
45+
**Always:**
46+
- Cite specific evidence (user reports, performance data, failure modes)
47+
- Justify recommendations with technical rationale
48+
- Acknowledge trade-offs (no perfect solutions)
49+
- Be specific about APIs, libraries, file paths
50+
51+
**Never:**
52+
- Hype ("revolutionary", "game-changing")
53+
- Hand-waving ("we'll figure it out later")
54+
- Unsubstantiated claims ("users will love this")
55+
- Vague timelines ("soon", "eventually")
56+
57+
### Wave Restructuring Pattern
58+
59+
When a proposal invalidates existing wave structure:
60+
1. **Acknowledge the shift:** "This becomes Wave 0 (Foundation)"
61+
2. **Cascade impacts:** Adjust downstream waves (Wave 1, Wave 2, Wave 3)
62+
3. **Preserve non-blocking work:** Identify what can proceed in parallel
63+
4. **Update dependencies:** Document new blocking relationships
64+
65+
**Example (Interactive Shell):**
66+
- Wave 0 (NEW): Interactive Shell — blocks all other waves
67+
- Wave 1 (ADJUSTED): npm Distribution — shell bundled in cli.js
68+
- Wave 2 (DEFERRED): SquadUI — waits for shell foundation
69+
- Wave 3 (ADJUSTED): Public Docs — now documents shell as primary interface
70+
71+
### Decision Framing
72+
73+
**Format:** "Recommendation: X (recommended) or alternatives?"
74+
75+
**Components:**
76+
- Recommendation (pick one, justify)
77+
- Alternatives (what else was considered)
78+
- Decision rationale (why recommended option wins)
79+
- Needs sign-off from (which agents/roles must approve)
80+
81+
**Example:**
82+
```
83+
### 1. Terminal UI Library: `ink` (recommended) or alternatives?
84+
85+
**Recommendation:** `ink`
86+
**Alternatives:** `blessed`, raw readline
87+
**Decision rationale:** Component model enables testable UI. Battle-tested ecosystem.
88+
89+
**Needs sign-off from:** Brady (product direction), Fortier (runtime performance)
90+
```
91+
92+
### Risk Documentation
93+
94+
**Format per risk:**
95+
- **Risk:** Specific failure mode
96+
- **Likelihood:** Low / Medium / High (not percentages)
97+
- **Impact:** Low / Medium / High
98+
- **Mitigation:** Concrete actions (measurable)
99+
100+
**Example:**
101+
```
102+
### Risk 2: SDK Streaming Reliability
103+
104+
**Risk:** SDK streaming events might drop messages or arrive out of order.
105+
**Likelihood:** Low (SDK is production-grade).
106+
**Impact:** High — broken streaming makes shell unusable.
107+
108+
**Mitigation:**
109+
- Add integration test: Send 1000-message stream, verify all deltas arrive in order
110+
- Implement fallback: If streaming fails, fall back to polling session state
111+
- Log all SDK events to `.squad/orchestration-log/sdk-events.jsonl` for debugging
112+
```
113+
114+
## Examples
115+
116+
**File references from interactive shell proposal:**
117+
- Full proposal: `docs/proposals/squad-interactive-shell.md`
118+
- User directive: `.squad/decisions/inbox/copilot-directive-2026-02-21T202535Z.md`
119+
- Team decisions: `.squad/decisions.md`
120+
- Current architecture: `docs/architecture/module-map.md`, `docs/prd-23-release-readiness.md`
121+
122+
**Key patterns demonstrated:**
123+
1. Read user directive first (understand the "why")
124+
2. Survey current architecture (module map, existing waves)
125+
3. Research SDK APIs (exploration task to validate feasibility)
126+
4. Document problem with specific evidence (unreliable handoffs, zero visibility, UX mismatch)
127+
5. Propose solution with technical specifics (ink components, SDK session management, spawn.ts module)
128+
6. Restructure waves when foundation shifts (Wave 0 becomes blocker)
129+
7. Preserve backward compatibility (squad.agent.md still works, VS Code mode unchanged)
130+
8. Frame decisions explicitly (5 key decisions with recommendations)
131+
9. Document risks with mitigations (5 risks, each with concrete actions)
132+
10. Define scope (what's in v1 vs. deferred)
133+
134+
## Anti-Patterns
135+
136+
**Avoid:**
137+
- ❌ Proposals without problem statements (solution-first thinking)
138+
- ❌ Vague architecture ("we'll use a shell") — be specific (ink components, session registry, spawn.ts)
139+
- ❌ Ignoring existing work — always document impact on waves/milestones
140+
- ❌ No risk analysis — every architecture has risks, document them
141+
- ❌ Unbounded scope — draw the v1 line explicitly
142+
- ❌ Missing decision ownership — always say "needs sign-off from X"
143+
- ❌ No backward compatibility plan — users don't care about your replatform
144+
- ❌ Hand-waving timelines ("a few weeks") — be specific (2-3 weeks, 1 engineer full-time)
145+
146+
**Red flags in proposal reviews:**
147+
- "Users will love this" (citation needed)
148+
- "We'll figure out X later" (scope creep incoming)
149+
- "This is revolutionary" (tone ceiling violation)
150+
- No section on "What Stays the Same" (regression risk)
151+
- No risks documented (wishful thinking)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
name: "ci-validation-gates"
3+
description: "Defensive CI/CD patterns: semver validation, token checks, retry logic, draft detection — earned from v0.8.22"
4+
domain: "ci-cd"
5+
confidence: "high"
6+
source: "extracted from Drucker and Trejo charters — earned knowledge from v0.8.22 release incident"
7+
---
8+
9+
## Context
10+
11+
CI workflows must be defensive. These patterns were learned from the v0.8.22 release disaster where invalid semver, wrong token types, missing retry logic, and draft releases caused a multi-hour outage. Both Drucker (CI/CD) and Trejo (Release Manager) carried this knowledge in their charters — now centralized here.
12+
13+
## Patterns
14+
15+
### Semver Validation Gate
16+
Every publish workflow MUST validate version format before `npm publish`. 4-part versions (e.g., 0.8.21.4) are NOT valid semver — npm mangles them.
17+
18+
```yaml
19+
- name: Validate semver
20+
run: |
21+
VERSION="${{ github.event.release.tag_name }}"
22+
VERSION="${VERSION#v}"
23+
if ! npx semver "$VERSION" > /dev/null 2>&1; then
24+
echo "❌ Invalid semver: $VERSION"
25+
echo "Only 3-part versions (X.Y.Z) or prerelease (X.Y.Z-tag.N) are valid."
26+
exit 1
27+
fi
28+
echo "✅ Valid semver: $VERSION"
29+
```
30+
31+
### NPM Token Type Verification
32+
NPM_TOKEN MUST be an Automation token, not a User token with 2FA:
33+
- User tokens require OTP — CI can't provide it → EOTP error
34+
- Create Automation tokens at npmjs.com → Settings → Access Tokens → Automation
35+
- Verify before first publish in any workflow
36+
37+
### Retry Logic for npm Registry Propagation
38+
npm registry uses eventual consistency. After `npm publish` succeeds, the package may not be immediately queryable.
39+
- Propagation: typically 5-30s, up to 2min in rare cases
40+
- All verify steps: 5 attempts, 15-second intervals
41+
- Log each attempt: "Attempt 1/5: Checking package..."
42+
- Exit loop on success, fail after max attempts
43+
44+
```yaml
45+
- name: Verify package (with retry)
46+
run: |
47+
MAX_ATTEMPTS=5
48+
WAIT_SECONDS=15
49+
for attempt in $(seq 1 $MAX_ATTEMPTS); do
50+
echo "Attempt $attempt/$MAX_ATTEMPTS: Checking $PACKAGE@$VERSION..."
51+
if npm view "$PACKAGE@$VERSION" version > /dev/null 2>&1; then
52+
echo "✅ Package verified"
53+
exit 0
54+
fi
55+
[ $attempt -lt $MAX_ATTEMPTS ] && sleep $WAIT_SECONDS
56+
done
57+
echo "❌ Failed to verify after $MAX_ATTEMPTS attempts"
58+
exit 1
59+
```
60+
61+
### Draft Release Detection
62+
Draft releases don't emit `release: published` event. Workflows MUST:
63+
- Trigger on `release: published` (NOT `created`)
64+
- If using workflow_dispatch: verify release is published via GitHub API before proceeding
65+
66+
### Build Script Protection
67+
Set `SKIP_BUILD_BUMP=1` (or `$env:SKIP_BUILD_BUMP = "1"` on Windows) before ANY release build. bump-build.mjs is for dev builds ONLY — it silently mutates versions.
68+
69+
## Known Failure Modes (v0.8.22 Incident)
70+
71+
| # | What Happened | Root Cause | Prevention |
72+
|---|---------------|-----------|------------|
73+
| 1 | 4-part version published, npm mangled it | No semver validation gate | `npx semver` check before every publish |
74+
| 2 | CI failed 5+ times with EOTP | User token with 2FA | Automation token only |
75+
| 3 | Verify returned false 404 | No retry logic for propagation | 5 attempts, 15s intervals |
76+
| 4 | Workflow never triggered | Draft release doesn't emit event | Never create draft releases |
77+
| 5 | Version mutated during release | bump-build.mjs ran in release | SKIP_BUILD_BUMP=1 |
78+
79+
## Anti-Patterns
80+
- ❌ Publishing without semver validation gate
81+
- ❌ Single-shot verification without retry
82+
- ❌ Hard-coded secrets in workflows
83+
- ❌ Silent CI failures — every error needs actionable output with remediation
84+
- ❌ Assuming npm publish is instantly queryable
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Skill: CLI Command Wiring
2+
3+
**Bug class:** Commands implemented in `packages/squad-cli/src/cli/commands/` but never routed in `cli-entry.ts`.
4+
5+
## Checklist — Adding a New CLI Command
6+
7+
1. **Create command file** in `packages/squad-cli/src/cli/commands/<name>.ts`
8+
- Export a `run<Name>(cwd, options)` async function (or class with static methods for utility modules)
9+
10+
2. **Add routing block** in `packages/squad-cli/src/cli-entry.ts` inside `main()`:
11+
```ts
12+
if (cmd === '<name>') {
13+
const { run<Name> } = await import('./cli/commands/<name>.js');
14+
// parse args, call function
15+
await run<Name>(process.cwd(), options);
16+
return;
17+
}
18+
```
19+
20+
3. **Add help text** in the help section of `cli-entry.ts` (search for `Commands:`):
21+
```ts
22+
console.log(` ${BOLD}<name>${RESET} <description>`);
23+
console.log(` Usage: <name> [flags]`);
24+
```
25+
26+
4. **Verify both exist** — the recurring bug is doing step 1 but missing steps 2-3.
27+
28+
## Wiring Patterns by Command Type
29+
30+
| Type | Example | How to wire |
31+
|------|---------|-------------|
32+
| Standard command | `export.ts`, `build.ts` | `run*()` function, parse flags from `args` |
33+
| Placeholder command | `loop`, `hire` | Inline in cli-entry.ts, prints pending message |
34+
| Utility/check module | `rc-tunnel.ts`, `copilot-bridge.ts` | Wire as diagnostic check (e.g., `isDevtunnelAvailable()`) |
35+
| Subcommand of another | `init-remote.ts` | Already used inside parent + standalone alias |
36+
37+
## Common Import Pattern
38+
39+
```ts
40+
import { BOLD, RESET, DIM, RED, GREEN, YELLOW } from './cli/core/output.js';
41+
```
42+
43+
Use dynamic `await import()` for command modules to keep startup fast (lazy loading).
44+
45+
## History
46+
47+
- **#237 / PR #244:** 4 commands wired (rc, copilot-bridge, init-remote, rc-tunnel). aspire, link, loop, hire were already present.

0 commit comments

Comments
 (0)